Initial test bootstrap.
This commit is contained in:
parent
6c618749f1
commit
4b308f6c32
94 changed files with 2543 additions and 681 deletions
|
@ -12,7 +12,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
// Start the gui app
|
// Start the gui app
|
||||||
auto app = NotesTk(std::move(args));
|
auto app = NotesTk(std::move(args));
|
||||||
//app.setUiInterfaceBackend(UiInterfaceFactory::Backend::X11_RASTER);
|
app.setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND_RASTER);
|
||||||
app.run();
|
app.run();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
20
bootstrap.sh
Executable file
20
bootstrap.sh
Executable 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
|
78
src/base/compiler/KScope.cpp
Normal file
78
src/base/compiler/KScope.cpp
Normal 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();
|
||||||
|
}
|
86
src/base/compiler/KScope.h
Normal file
86
src/base/compiler/KScope.h
Normal 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;
|
||||||
|
};
|
|
@ -33,8 +33,8 @@ public:
|
||||||
bool hitBufferFull() const;
|
bool hitBufferFull() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool lookAheadSourceEmpty() const;
|
bool lookAheadSourceEmpty() const;
|
||||||
|
|
||||||
unsigned char getSearchBufferItem(unsigned index) const;
|
unsigned char getSearchBufferItem(unsigned index) const;
|
||||||
|
|
||||||
unsigned lookAheadForMatchingChars(unsigned searchIndex);
|
unsigned lookAheadForMatchingChars(unsigned searchIndex);
|
||||||
|
|
|
@ -40,8 +40,11 @@ list(APPEND SOURCES
|
||||||
Dictionary.cpp
|
Dictionary.cpp
|
||||||
Color.cpp
|
Color.cpp
|
||||||
CommandLineArgs.cpp
|
CommandLineArgs.cpp
|
||||||
|
memory/Allocator.cpp
|
||||||
data_structures/RawTree.cpp
|
data_structures/RawTree.cpp
|
||||||
data_structures/Tree.cpp
|
data_structures/Tree.cpp
|
||||||
|
data_structures/Vector.cpp
|
||||||
|
data_structures/String.cpp
|
||||||
loggers/FileLogger.cpp
|
loggers/FileLogger.cpp
|
||||||
file_utilities/Directory.cpp
|
file_utilities/Directory.cpp
|
||||||
file_utilities/File.cpp
|
file_utilities/File.cpp
|
||||||
|
@ -81,6 +84,7 @@ target_include_directories(${MODULE_NAME} PUBLIC
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/memory
|
${CMAKE_CURRENT_SOURCE_DIR}/memory
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/streams
|
${CMAKE_CURRENT_SOURCE_DIR}/streams
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/http
|
${CMAKE_CURRENT_SOURCE_DIR}/http
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/base_types
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/data_structures
|
${CMAKE_CURRENT_SOURCE_DIR}/data_structures
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/serializers
|
${CMAKE_CURRENT_SOURCE_DIR}/serializers
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/xml
|
${CMAKE_CURRENT_SOURCE_DIR}/xml
|
||||||
|
|
|
@ -34,6 +34,77 @@ std::unique_ptr<Color> Color::Create(unsigned char r, unsigned char g, unsigned
|
||||||
return std::make_unique<Color>(r, g, b, a);
|
return std::make_unique<Color>(r, g, b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t Color::getSize() const
|
||||||
|
{
|
||||||
|
return getSize(mFormat, mBitDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t Color::getSize(Format format, unsigned bitDepth)
|
||||||
|
{
|
||||||
|
return getNumChannels(format) * bitDepth / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t Color::getNumChannels(Format format)
|
||||||
|
{
|
||||||
|
if (format == Format::GRAYSCALE || format == Format::LUT)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Color::getByte(std::size_t index) const
|
||||||
|
{
|
||||||
|
if (mFormat == Format::GRAYSCALE || mFormat == Format::LUT)
|
||||||
|
{
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
throw std::range_error("Color index out of range in getByte()");
|
||||||
|
}
|
||||||
|
return mValue;
|
||||||
|
}
|
||||||
|
else if (mFormat == Format::ARGB)
|
||||||
|
{
|
||||||
|
switch(index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return mAlpha * 255;
|
||||||
|
case 1:
|
||||||
|
return mR;
|
||||||
|
case 2:
|
||||||
|
return mG;
|
||||||
|
case 3:
|
||||||
|
return mB;
|
||||||
|
default:
|
||||||
|
throw std::range_error("Color index out of range in getByte()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return mR;
|
||||||
|
case 1:
|
||||||
|
return mG;
|
||||||
|
case 2:
|
||||||
|
return mB;
|
||||||
|
case 3:
|
||||||
|
return mAlpha * 255;
|
||||||
|
default:
|
||||||
|
throw std::range_error("Color index out of range in getByte()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Color::setAlpha(float alpha)
|
||||||
|
{
|
||||||
|
mAlpha = static_cast<double>(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<Color> Color::Create(const Color& color)
|
std::unique_ptr<Color> Color::Create(const Color& color)
|
||||||
{
|
{
|
||||||
return std::make_unique<Color>(color);
|
return std::make_unique<Color>(color);
|
||||||
|
|
|
@ -3,10 +3,20 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
class Color
|
class Color
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum class Format
|
||||||
|
{
|
||||||
|
GRAYSCALE,
|
||||||
|
GRAYSCALE_ALPHA,
|
||||||
|
LUT,
|
||||||
|
RGB,
|
||||||
|
ARGB,
|
||||||
|
RGBA
|
||||||
|
};
|
||||||
|
|
||||||
Color(const std::string& hexString);
|
Color(const std::string& hexString);
|
||||||
Color(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, double a = 1.0);
|
Color(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, double a = 1.0);
|
||||||
|
@ -25,10 +35,15 @@ public:
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
void setAlpha(float alpha)
|
std::size_t getSize() const;
|
||||||
{
|
|
||||||
mAlpha = static_cast<double>(alpha);
|
static std::size_t getNumChannels(Format format);
|
||||||
}
|
|
||||||
|
static std::size_t getSize(Format format, unsigned bitDepth);
|
||||||
|
|
||||||
|
uint8_t getByte(std::size_t index) const;
|
||||||
|
|
||||||
|
void setAlpha(float alpha);
|
||||||
|
|
||||||
bool operator==(const Color& rhs) const
|
bool operator==(const Color& rhs) const
|
||||||
{
|
{
|
||||||
|
@ -49,7 +64,10 @@ private:
|
||||||
unsigned char mR{0};
|
unsigned char mR{0};
|
||||||
unsigned char mG{0};
|
unsigned char mG{0};
|
||||||
unsigned char mB{0};
|
unsigned char mB{0};
|
||||||
|
unsigned char mValue{0};
|
||||||
double mAlpha{0.0};
|
double mAlpha{0.0};
|
||||||
|
unsigned mBitDepth{8};
|
||||||
|
Format mFormat{Format::RGBA};
|
||||||
};
|
};
|
||||||
|
|
||||||
using ColorPtr = std::shared_ptr<Color>;
|
using ColorPtr = std::shared_ptr<Color>;
|
||||||
|
|
|
@ -34,37 +34,37 @@ void CommandLineArgs::initialize(CommandLineArgs* args)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CommandLineArgs> CommandLineArgs::Create()
|
Ptr<CommandLineArgs> CommandLineArgs::Create()
|
||||||
{
|
{
|
||||||
return std::make_unique<CommandLineArgs>();
|
return Ptr<CommandLineArgs>::create();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path CommandLineArgs::getLaunchPath()
|
FileSystemPath CommandLineArgs::getLaunchPath()
|
||||||
{
|
{
|
||||||
return mLaunchPath;
|
return mLaunchPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineArgs::recordLaunchPath()
|
void CommandLineArgs::recordLaunchPath()
|
||||||
{
|
{
|
||||||
mLaunchPath = std::filesystem::current_path();
|
mLaunchPath = FileSystemPath::current_dir();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineArgs::process(int argc, char *argv[])
|
void CommandLineArgs::process(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
for(int idx=0; idx<argc; idx++)
|
for(int idx=0; idx<argc; idx++)
|
||||||
{
|
{
|
||||||
mArugments.push_back(std::string(argv[idx]));
|
mArugments.push_back(String(argv[idx]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineArgs::process(const std::vector<std::string>& args)
|
void CommandLineArgs::process(const Vector<String>& args)
|
||||||
{
|
{
|
||||||
mArugments = args;
|
mArugments = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> CommandLineArgs::getUserArgs() const
|
Vector<String> CommandLineArgs::getUserArgs() const
|
||||||
{
|
{
|
||||||
std::vector<std::string> user_args;
|
Vector<String> user_args;
|
||||||
for(unsigned idx=1; idx<mArugments.size(); idx++)
|
for(unsigned idx=1; idx<mArugments.size(); idx++)
|
||||||
{
|
{
|
||||||
user_args.push_back(mArugments[idx]);
|
user_args.push_back(mArugments[idx]);
|
||||||
|
@ -72,7 +72,7 @@ std::vector<std::string> CommandLineArgs::getUserArgs() const
|
||||||
return user_args;
|
return user_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string> CommandLineArgs::getArgs() const
|
const Vector<String> CommandLineArgs::getArgs() const
|
||||||
{
|
{
|
||||||
return mArugments;
|
return mArugments;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,31 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include "Pointer.h"
|
||||||
#include <vector>
|
#include "Vector.h"
|
||||||
#include <string>
|
#include "String.h"
|
||||||
#include <filesystem>
|
#include "FileSystemPath.h"
|
||||||
|
|
||||||
class CommandLineArgs
|
class CommandLineArgs
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CommandLineArgs();
|
CommandLineArgs();
|
||||||
|
|
||||||
static std::unique_ptr<CommandLineArgs> Create();
|
static Ptr<CommandLineArgs> Create();
|
||||||
|
|
||||||
std::filesystem::path getLaunchPath();
|
FileSystemPath getLaunchPath();
|
||||||
|
|
||||||
const std::vector<std::string> getArgs() const;
|
const Vector<String> getArgs() const;
|
||||||
|
|
||||||
std::vector<std::string> getUserArgs() const;
|
Vector<String> getUserArgs() const;
|
||||||
|
|
||||||
static void initialize(CommandLineArgs* args);
|
static void initialize(CommandLineArgs* args);
|
||||||
|
|
||||||
void process(int argc, char *argv[]);
|
void process(int argc, char *argv[]);
|
||||||
|
|
||||||
void process(const std::vector<std::string>& args);
|
void process(const Vector<String>& args);
|
||||||
|
|
||||||
void recordLaunchPath();
|
void recordLaunchPath();
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> mArugments;
|
Vector<String> mArugments;
|
||||||
std::filesystem::path mLaunchPath;
|
FileSystemPath mLaunchPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
using CommandLineArgsUPtr = std::unique_ptr<CommandLineArgs>;
|
|
||||||
|
|
11
src/base/core/Serializeable.h
Normal file
11
src/base/core/Serializeable.h
Normal 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;
|
||||||
|
};
|
12
src/base/core/base_types/ByteTypes.h
Normal file
12
src/base/core/base_types/ByteTypes.h
Normal 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;
|
11
src/base/core/base_types/Error.cpp
Normal file
11
src/base/core/base_types/Error.cpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "Error.h"
|
||||||
|
|
||||||
|
Error::Error(const String& msg)
|
||||||
|
: m_message(msg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const String& Error::msg() const
|
||||||
|
{
|
||||||
|
return m_message;
|
||||||
|
}
|
15
src/base/core/base_types/Error.h
Normal file
15
src/base/core/base_types/Error.h
Normal 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;
|
||||||
|
};
|
17
src/base/core/base_types/Index.cpp
Normal file
17
src/base/core/base_types/Index.cpp
Normal 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;
|
||||||
|
}
|
19
src/base/core/base_types/Index.h
Normal file
19
src/base/core/base_types/Index.h
Normal 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};
|
||||||
|
};
|
41
src/base/core/base_types/Result.h
Normal file
41
src/base/core/base_types/Result.h
Normal 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
0
src/base/core/build.toml
Normal file
|
@ -1,8 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include "Vector.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class CircleBuffer
|
class CircleBuffer
|
||||||
|
@ -60,5 +58,5 @@ public:
|
||||||
private:
|
private:
|
||||||
std::size_t mStartPointer{0};
|
std::size_t mStartPointer{0};
|
||||||
std::size_t mEndPointer{0};
|
std::size_t mEndPointer{0};
|
||||||
std::vector<T> mData;
|
Vector<T> mData;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include "Error.h"
|
||||||
#include <string>
|
#include "Vector.h"
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
class AbstractList
|
class AbstractList
|
||||||
{
|
{
|
||||||
|
@ -20,7 +19,7 @@ public:
|
||||||
|
|
||||||
void initializeTo(std::size_t size, T value)
|
void initializeTo(std::size_t size, T value)
|
||||||
{
|
{
|
||||||
mData = std::vector<T>(size, value);
|
mData = Vector<T>(size, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* getDataPtr() const
|
const T* getDataPtr() const
|
||||||
|
@ -28,7 +27,7 @@ public:
|
||||||
return mData.data();
|
return mData.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<T>& getData() const
|
const Vector<T>& getData() const
|
||||||
{
|
{
|
||||||
return mData;
|
return mData;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +45,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setData(const std::vector<T>& data)
|
void setData(const Vector<T>& data)
|
||||||
{
|
{
|
||||||
mData = data;
|
mData = data;
|
||||||
}
|
}
|
||||||
|
@ -65,5 +64,5 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<T> mData;
|
Vector<T> mData;
|
||||||
};
|
};
|
||||||
|
|
6
src/base/core/data_structures/Map.h
Normal file
6
src/base/core/data_structures/Map.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
class Map{
|
||||||
|
|
||||||
|
};
|
29
src/base/core/data_structures/Optional.h
Normal file
29
src/base/core/data_structures/Optional.h
Normal 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;
|
||||||
|
};
|
27
src/base/core/data_structures/Pair.h
Normal file
27
src/base/core/data_structures/Pair.h
Normal 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;
|
||||||
|
};
|
|
@ -1,7 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class RawNode
|
class RawNode
|
||||||
{
|
{
|
||||||
|
|
232
src/base/core/data_structures/String.cpp
Normal file
232
src/base/core/data_structures/String.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
59
src/base/core/data_structures/String.h
Normal file
59
src/base/core/data_structures/String.h
Normal 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;
|
||||||
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include "Pointer.h"
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Node
|
class Node
|
||||||
|
@ -10,7 +10,7 @@ public:
|
||||||
: mData(data)
|
: mData(data)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void addChild(std::unique_ptr<Node> child)
|
void addChild(Ptr<Node> child)
|
||||||
{
|
{
|
||||||
if(!mLeftChild)
|
if(!mLeftChild)
|
||||||
{
|
{
|
||||||
|
@ -45,12 +45,12 @@ public:
|
||||||
private:
|
private:
|
||||||
T mData;
|
T mData;
|
||||||
unsigned char mTag{0};
|
unsigned char mTag{0};
|
||||||
std::unique_ptr<Node> mLeftChild;
|
Ptr<Node> mLeftChild;
|
||||||
std::unique_ptr<Node> mRightChild;
|
Ptr<Node> mRightChild;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using NodePtr = std::unique_ptr<Node<T> >;
|
using NodePtr = Ptr<Node<T> >;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Tree
|
class Tree
|
||||||
|
|
0
src/base/core/data_structures/Vector.cpp
Normal file
0
src/base/core/data_structures/Vector.cpp
Normal file
233
src/base/core/data_structures/Vector.h
Normal file
233
src/base/core/data_structures/Vector.h
Normal 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};
|
||||||
|
};
|
|
@ -1,44 +1,40 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ByteTypes.h"
|
||||||
|
#include "String.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdint.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class ByteUtils
|
class ByteUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Word = int16_t;
|
static bool MostSignificantBitIsOne(Byte c);
|
||||||
using DWord = int32_t;
|
|
||||||
using QWord = int64_t;
|
|
||||||
|
|
||||||
static bool MostSignificantBitIsOne(char c);
|
|
||||||
|
|
||||||
static Word GetWordFirstBit(const Word word);
|
static Word GetWordFirstBit(const Word word);
|
||||||
|
|
||||||
static Word GetWordLastByte(const Word word);
|
static Word GetWordLastByte(const Word word);
|
||||||
|
|
||||||
static unsigned char getByteN(uint32_t input, unsigned n);
|
static Byte getByteN(DWord input, std::size_t n);
|
||||||
|
|
||||||
static unsigned char getHigherNBits(unsigned char input, unsigned num);
|
static Byte getHigherNBits(Byte input, std::size_t num);
|
||||||
|
|
||||||
static unsigned char getLowerNBits(uint32_t input, unsigned num);
|
static Byte getLowerNBits(DWord input, std::size_t num);
|
||||||
|
|
||||||
static unsigned char getTwoBitsAtN(unsigned char input, unsigned n);
|
static Byte getTwoBitsAtN(Byte input, std::size_t n);
|
||||||
|
|
||||||
static unsigned char getMBitsAtN(unsigned char input, unsigned m, unsigned n);
|
static Byte getMBitsAtN(Byte input, std::size_t m, std::size_t n);
|
||||||
|
|
||||||
static bool getBitN(uint32_t input, unsigned n);
|
static bool getBitN(DWord input, std::size_t n);
|
||||||
|
|
||||||
static unsigned char getFromString(const std::string& string);
|
static Byte getFromString(const String& string);
|
||||||
|
|
||||||
static std::string toString(uint32_t input, unsigned length = 8);
|
static String toString(DWord input, std::size_t length = 8);
|
||||||
|
|
||||||
static uint32_t mirror(uint32_t input, unsigned length=0);
|
static DWord mirror(DWord input, std::size_t length=0);
|
||||||
|
|
||||||
static void ReverseBuffer(char* buffer, char* reverse, unsigned size, unsigned targetSize);
|
static void ReverseBuffer(Byte* buffer, Byte* reverse, std::size_t size, std::size_t targetSize);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static T ToType(char* buffer, bool reverse = true)
|
static T ToType(Byte* buffer, bool reverse = true)
|
||||||
{
|
{
|
||||||
T result {0};
|
T result {0};
|
||||||
if(reverse)
|
if(reverse)
|
||||||
|
@ -54,17 +50,17 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Word ToWord(char* buffer, bool reverse = true);
|
static Word ToWord(Byte* buffer, bool reverse = true);
|
||||||
|
|
||||||
static DWord ToDWord(char* buffer, bool reverse = true);
|
static DWord ToDWord(Byte* buffer, bool reverse = true);
|
||||||
|
|
||||||
static QWord ToQWord(char* buffer, bool reverse = true);
|
static QWord ToQWord(Byte* buffer, bool reverse = true);
|
||||||
|
|
||||||
static bool Compare(char* buffer, const char* tag, unsigned size);
|
static bool Compare(Byte* buffer, const char* tag, std::size_t size);
|
||||||
|
|
||||||
static bool CompareDWords(char* buffer, const char* tag);
|
static bool CompareDWords(Byte* buffer, const char* tag);
|
||||||
|
|
||||||
static bool CompareWords(char* buffer, const char* tag);
|
static bool CompareWords(Byte* buffer, const char* tag);
|
||||||
|
|
||||||
static const int BYTE_FIRST_BIT = 0x40; // 1000 0000
|
static const int BYTE_FIRST_BIT = 0x40; // 1000 0000
|
||||||
static const Word WORD_FIRST_BIT = static_cast<Word>(0x8000); // 1000 0000 - 0000 0000
|
static const Word WORD_FIRST_BIT = static_cast<Word>(0x8000); // 1000 0000 - 0000 0000
|
||||||
|
|
35
src/base/core/encoding/CharUtils.cpp
Normal file
35
src/base/core/encoding/CharUtils.cpp
Normal 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';
|
||||||
|
}
|
17
src/base/core/encoding/CharUtils.h
Normal file
17
src/base/core/encoding/CharUtils.h
Normal 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);
|
||||||
|
};
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ByteTypes.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,84 @@
|
||||||
#include "Directory.h"
|
#include "Directory.h"
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
std::vector<Path> Directory::getFilesWithExtension(const Path& path, const std::string& extension, bool recursive)
|
Vector<FileSystemPath> Directory::getSubdirectories(const FileSystemPath& path)
|
||||||
{
|
{
|
||||||
std::vector<Path> paths;
|
Vector<FileSystemPath> ret;
|
||||||
if (std::filesystem::is_directory(path))
|
auto dirp = ::opendir(path.as_string().raw());
|
||||||
|
while(auto ep = ::readdir(dirp))
|
||||||
{
|
{
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(path))
|
auto rel_path = String(ep->d_name);
|
||||||
|
if (rel_path == "." || rel_path == "..")
|
||||||
{
|
{
|
||||||
if (std::filesystem::is_regular_file(entry) && entry.path().extension() == extension)
|
continue;
|
||||||
{
|
|
||||||
paths.push_back(entry.path());
|
|
||||||
}
|
}
|
||||||
else if(recursive && std::filesystem::is_directory(entry))
|
|
||||||
|
auto full_path = path.join(rel_path);
|
||||||
|
struct stat sb;
|
||||||
|
auto rc = lstat(full_path.as_string().raw(), &sb);
|
||||||
|
if (rc == -1)
|
||||||
{
|
{
|
||||||
const auto child_paths = getFilesWithExtension(entry, extension, recursive);
|
printf("Got error");
|
||||||
paths.insert(paths.end(), child_paths.begin(), child_paths.end());
|
}
|
||||||
|
if (S_ISDIR(sb.st_mode))
|
||||||
|
{
|
||||||
|
printf("Adding full path: %s\n", full_path.as_string().raw());
|
||||||
|
ret.push_back(full_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::closedir(dirp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<FileSystemPath> Directory::getFiles(const FileSystemPath& path, bool recursive)
|
||||||
|
{
|
||||||
|
Vector<FileSystemPath> paths;
|
||||||
|
if (path.is_directory())
|
||||||
|
{
|
||||||
|
for (const auto& entry : getSubdirectories(path))
|
||||||
|
{
|
||||||
|
if (entry.is_regular_file())
|
||||||
|
{
|
||||||
|
paths.push_back(entry);
|
||||||
|
}
|
||||||
|
else if(recursive && entry.is_directory())
|
||||||
|
{
|
||||||
|
const auto child_paths = getFiles(entry, recursive);
|
||||||
|
paths.extend(child_paths);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Directory::createIfNotExisting(const Path& path)
|
Vector<FileSystemPath> Directory::getFilesWithExtension(const FileSystemPath& path, const String& extension, bool recursive)
|
||||||
{
|
{
|
||||||
Path working_path;
|
Vector<FileSystemPath> paths;
|
||||||
if (std::filesystem::is_directory(path))
|
if (path.is_directory())
|
||||||
|
{
|
||||||
|
for (const auto& entry : getSubdirectories(path))
|
||||||
|
{
|
||||||
|
if (entry.is_regular_file() && entry.extension() == extension)
|
||||||
|
{
|
||||||
|
paths.push_back(entry);
|
||||||
|
}
|
||||||
|
else if(recursive && entry.is_directory())
|
||||||
|
{
|
||||||
|
const auto child_paths = getFilesWithExtension(entry, extension, recursive);
|
||||||
|
paths.extend(child_paths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Directory::create(const FileSystemPath& path, bool existsOk)
|
||||||
|
{
|
||||||
|
(void)existsOk;
|
||||||
|
FileSystemPath working_path;
|
||||||
|
if (path.is_directory())
|
||||||
{
|
{
|
||||||
working_path = path;
|
working_path = path;
|
||||||
}
|
}
|
||||||
|
@ -33,8 +87,8 @@ void Directory::createIfNotExisting(const Path& path)
|
||||||
working_path = path.parent_path();
|
working_path = path.parent_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std::filesystem::exists(working_path))
|
if (!working_path.exists())
|
||||||
{
|
{
|
||||||
std::filesystem::create_directories(working_path);
|
//std::filesystem::create_directories(working_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include "Vector.h"
|
||||||
#include <filesystem>
|
#include "FileSystemPath.h"
|
||||||
|
|
||||||
using Path = std::filesystem::path;
|
|
||||||
|
|
||||||
class Directory
|
class Directory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void createIfNotExisting(const Path& path);
|
static Vector<FileSystemPath> getSubdirectories(const FileSystemPath& path);
|
||||||
|
|
||||||
static std::vector<Path> getFilesWithExtension(const Path& path, const std::string& extension, bool recursive=false);
|
static void create(const FileSystemPath& path, bool existsOK = false);
|
||||||
|
|
||||||
|
static Vector<FileSystemPath> getFiles(const FileSystemPath& path, bool recursive=false);
|
||||||
|
|
||||||
|
static Vector<FileSystemPath> getFilesWithExtension(const FileSystemPath& path, const String& extension, bool recursive=false);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,17 +1,116 @@
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
|
|
||||||
#include "FileLogger.h"
|
//#include "FileLogger.h"
|
||||||
#include "ByteUtils.h"
|
#include "ByteUtils.h"
|
||||||
|
#include "Directory.h"
|
||||||
|
#include "Result.h"
|
||||||
|
|
||||||
#include <streambuf>
|
#include <fcntl.h>
|
||||||
#include <sstream>
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
File::File(std::filesystem::path path)
|
class FileImpl
|
||||||
: mFullPath(path),
|
|
||||||
mInHandle(),
|
|
||||||
mOutHandle()
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
void do_open(const FileSystemPath& path, File::AccessMode accessMode)
|
||||||
|
{
|
||||||
|
int flags{0};
|
||||||
|
if (accessMode == File::AccessMode::Read)
|
||||||
|
{
|
||||||
|
flags |= O_RDONLY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flags |= O_WRONLY;
|
||||||
|
flags |= O_CREAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fd = ::open(path.as_string().raw(), flags);
|
||||||
|
if (accessMode == File::AccessMode::Read)
|
||||||
|
{
|
||||||
|
m_open_for_read = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_open_for_write = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_close()
|
||||||
|
{
|
||||||
|
::close(m_fd);
|
||||||
|
m_open_for_read = false;
|
||||||
|
m_open_for_write = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_ok() const
|
||||||
|
{
|
||||||
|
return m_valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_open_for_read() const
|
||||||
|
{
|
||||||
|
return m_open_for_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_open_for_write() const
|
||||||
|
{
|
||||||
|
return m_open_for_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<std::size_t> do_read(VecBytes& bytes)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
const auto rc = ::read(m_fd, bytes.data(), bytes.capacity());
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
const auto last_err = errno;
|
||||||
|
String msg(::strerror(last_err));
|
||||||
|
return Result<std::size_t>(Error(msg));
|
||||||
|
}
|
||||||
|
return Result<std::size_t>(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t do_write(const VecBytes& bytes)
|
||||||
|
{
|
||||||
|
return ::write(m_fd, bytes.data(), bytes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t do_write(const Vector<char>& bytes, int size = -1)
|
||||||
|
{
|
||||||
|
if (size > -1)
|
||||||
|
{
|
||||||
|
return ::write(m_fd, bytes.data(), size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ::write(m_fd, bytes.data(), bytes.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_size()
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
::fstat(m_fd, &buf);
|
||||||
|
m_size = buf.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_open_for_write{false};
|
||||||
|
bool m_open_for_read{false};
|
||||||
|
bool m_valid{false};
|
||||||
|
std::size_t m_size{0};
|
||||||
|
bool m_is_open{false};
|
||||||
|
int m_fd{-1};
|
||||||
|
};
|
||||||
|
|
||||||
|
File::File(const FileSystemPath& path)
|
||||||
|
: m_impl(Ptr<FileImpl>::create()),
|
||||||
|
m_path(path)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
File::~File()
|
File::~File()
|
||||||
|
@ -19,145 +118,149 @@ File::~File()
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string File::getExtension() const
|
String File::getExtension() const
|
||||||
{
|
{
|
||||||
return mFullPath.extension().string();
|
return m_path.extension();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string File::dumpBinary()
|
bool File::readBinary(VecBytes& buffer)
|
||||||
|
{
|
||||||
|
auto ok = open(AccessMode::Read, true);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_impl->update_size();
|
||||||
|
buffer.resize(m_impl->m_size);
|
||||||
|
const auto result = m_impl->do_read(buffer);
|
||||||
|
buffer.resize(result.value());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String File::readText()
|
||||||
|
{
|
||||||
|
VecBytes buffer;
|
||||||
|
auto ok = open(AccessMode::Read, true);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
m_impl->update_size();
|
||||||
|
buffer.resize(m_impl->m_size);
|
||||||
|
const auto result = m_impl->do_read(buffer);
|
||||||
|
if (!result.ok())
|
||||||
|
{
|
||||||
|
printf("Got error: %s\n", result.error().msg());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.resize(result.value());
|
||||||
|
return String(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
String File::dumpBinary()
|
||||||
{
|
{
|
||||||
open(AccessMode::Read);
|
open(AccessMode::Read);
|
||||||
|
|
||||||
std::stringstream sstr;
|
String sstr;
|
||||||
sstr << "Count | Binary | Decimal | ASCII \n";
|
sstr << "Count | Binary | Decimal | Hex | ASCII \n";
|
||||||
|
|
||||||
|
VecBytes buffer;
|
||||||
|
readBinary(buffer);
|
||||||
|
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
while(mInHandle->peek() != EOF)
|
/*
|
||||||
|
for(const auto byte : buffer)
|
||||||
{
|
{
|
||||||
const unsigned char val = static_cast<unsigned char>(mInHandle->get());
|
const auto ascii_val = std::isalpha(byte) ? byte : '.';
|
||||||
const unsigned char ascii_val = std::isalpha(val) ? val : '.';
|
String hex_sstr;
|
||||||
sstr << count << " | " << ByteUtils::toString(val) << " | " << static_cast<int>(val) << " | " << ascii_val << '\n';
|
hex_sstr << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(byte);
|
||||||
|
|
||||||
|
sstr << count << " | " << ByteUtils::toString(byte) << " | " << static_cast<int>(byte) << " | " << hex_sstr.str() << " | " << ascii_val << '\n';
|
||||||
if (count % 10 == 0)
|
if (count % 10 == 0)
|
||||||
{
|
{
|
||||||
sstr << "\n";
|
sstr << "\n";
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
const auto out = sstr.str();
|
*/
|
||||||
close();
|
close();
|
||||||
return out;
|
return sstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream* File::getInHandle() const
|
Optional<Byte> File::readNextByte()
|
||||||
{
|
{
|
||||||
return mInHandle.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ofstream* File::getOutHandle() const
|
|
||||||
{
|
|
||||||
return mOutHandle.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<unsigned char> File::readNextByte()
|
|
||||||
{
|
|
||||||
if (!mInHandle)
|
|
||||||
{
|
|
||||||
if (!open(AccessMode::Read))
|
if (!open(AccessMode::Read))
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return {};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mInHandle->good())
|
if (m_impl->is_ok())
|
||||||
{
|
{
|
||||||
if (auto val = mInHandle->get(); val == EOF)
|
VecBytes buffer(1);
|
||||||
|
m_impl->do_read(buffer);
|
||||||
|
if (buffer[0] == EOF)
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return {};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return val;
|
return buffer[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool File::open(AccessMode accessMode)
|
bool File::open(AccessMode accessMode, bool binary)
|
||||||
{
|
{
|
||||||
if (mFullPath.is_absolute() && !std::filesystem::exists(mFullPath.parent_path()))
|
if (m_path.is_absolute() && !m_path.parent_path().exists())
|
||||||
{
|
{
|
||||||
std::filesystem::create_directories(mFullPath.parent_path());
|
Directory::create(m_path.parent_path(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(accessMode == AccessMode::Read)
|
m_impl->do_open(m_path, accessMode);
|
||||||
{
|
|
||||||
auto flags = std::ifstream::in;
|
|
||||||
mInHandle = std::make_unique<std::ifstream>();
|
|
||||||
mInHandle->open(mFullPath, flags);
|
|
||||||
if (!mInHandle->is_open())
|
|
||||||
{
|
|
||||||
MLOG_ERROR("Failed to open file at :" << mFullPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto flags = std::ofstream::out;
|
|
||||||
mOutHandle = std::make_unique<std::ofstream>();
|
|
||||||
mOutHandle->open(mFullPath, flags);
|
|
||||||
if (!mOutHandle->is_open())
|
|
||||||
{
|
|
||||||
MLOG_ERROR("Failed to open file at :" << mFullPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::close()
|
void File::close()
|
||||||
{
|
{
|
||||||
if(mOutHandle)
|
m_impl->do_close();
|
||||||
{
|
|
||||||
mOutHandle->close();
|
|
||||||
}
|
|
||||||
if(mInHandle)
|
|
||||||
{
|
|
||||||
mInHandle->close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileFormat::Format File::inferFormat() const
|
FileFormat::Format File::inferFormat() const
|
||||||
{
|
{
|
||||||
const auto extension = getExtension();
|
//const auto extension = getExtension();
|
||||||
return FileFormat::inferFormat(extension);
|
//return FileFormat::inferFormat(extension);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::writeText(const std::string& text)
|
void File::writeText(const String& text)
|
||||||
{
|
{
|
||||||
bool had_to_open{false};
|
bool had_to_open{false};
|
||||||
if (!mOutHandle)
|
if (!m_impl->is_open_for_write())
|
||||||
{
|
{
|
||||||
had_to_open = true;
|
had_to_open = true;
|
||||||
if (!open(File::AccessMode::Write))
|
m_impl->do_open(m_path, File::AccessMode::Write);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(*mOutHandle) << text;
|
m_impl->do_write(text.data(), text.data().size() - 1);
|
||||||
|
|
||||||
if (had_to_open)
|
if (had_to_open)
|
||||||
{
|
{
|
||||||
close();
|
m_impl->do_close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> File::readLines()
|
Vector<String> File::readLines()
|
||||||
{
|
{
|
||||||
std::vector<std::string> content;
|
Vector<String> content;
|
||||||
|
|
||||||
|
/*
|
||||||
if (!pathExists())
|
if (!pathExists())
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
|
@ -168,18 +271,20 @@ std::vector<std::string> File::readLines()
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string str;
|
String str;
|
||||||
while(std::getline(*mInHandle, str))
|
while(std::getline(*mInHandle, str))
|
||||||
{
|
{
|
||||||
content.push_back(str);
|
content.push_back(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
close();
|
close();
|
||||||
|
*/
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string File::read()
|
String File::read()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (!pathExists())
|
if (!pathExists())
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
|
@ -190,31 +295,16 @@ std::string File::read()
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stringstream buffer;
|
String buffer;
|
||||||
buffer << mInHandle->rdbuf();
|
buffer << mInHandle->rdbuf();
|
||||||
|
|
||||||
close();
|
close();
|
||||||
return buffer.str();
|
*/
|
||||||
}
|
String buffer;
|
||||||
|
return buffer;
|
||||||
std::string File::readText()
|
|
||||||
{
|
|
||||||
if (!pathExists())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!open(AccessMode::Read))
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string str((std::istreambuf_iterator<char>(*mInHandle)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool File::pathExists() const
|
bool File::pathExists() const
|
||||||
{
|
{
|
||||||
return std::filesystem::exists(mFullPath);
|
return m_path.exists();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +1,53 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "FileFormats.h"
|
#include "FileFormats.h"
|
||||||
|
#include "FileSystemPath.h"
|
||||||
|
#include "Optional.h"
|
||||||
|
#include "String.h"
|
||||||
|
#include "ByteTypes.h"
|
||||||
|
#include "Pointer.h"
|
||||||
|
|
||||||
#include <filesystem>
|
class FileImpl;
|
||||||
#include <string>
|
|
||||||
#include <fstream>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
using Path = std::filesystem::path;
|
|
||||||
|
|
||||||
class File
|
class File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class AccessMode{
|
enum class AccessMode{
|
||||||
Read,
|
Read,
|
||||||
Write
|
Write,
|
||||||
|
ReadWrite
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
File(std::filesystem::path fullPath);
|
File(const FileSystemPath& path);
|
||||||
|
|
||||||
~File();
|
~File();
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
std::string dumpBinary();
|
String dumpBinary();
|
||||||
|
|
||||||
std::string getExtension() const;
|
String getExtension() const;
|
||||||
|
|
||||||
std::ifstream* getInHandle() const;
|
|
||||||
|
|
||||||
std::ofstream* getOutHandle() const;
|
|
||||||
|
|
||||||
FileFormat::Format inferFormat() const;
|
FileFormat::Format inferFormat() const;
|
||||||
|
|
||||||
std::string readText();
|
String readText();
|
||||||
|
|
||||||
std::vector<std::string> readLines();
|
Vector<String> readLines();
|
||||||
|
|
||||||
std::string read();
|
String read();
|
||||||
|
|
||||||
bool pathExists() const;
|
bool pathExists() const;
|
||||||
|
|
||||||
bool open(AccessMode mode);
|
bool open(AccessMode mode, bool binary = false);
|
||||||
|
|
||||||
std::optional<unsigned char> readNextByte();
|
bool readBinary(VecBytes& bytes);
|
||||||
|
|
||||||
void writeText(const std::string& text);
|
Optional<Byte> readNextByte();
|
||||||
|
|
||||||
|
void writeText(const String& text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::filesystem::path mFullPath;
|
Ptr<FileImpl> m_impl;
|
||||||
std::unique_ptr<std::ifstream> mInHandle;
|
FileSystemPath m_path;
|
||||||
std::unique_ptr<std::ofstream> mOutHandle;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
#include "Map.h"
|
||||||
#include <string>
|
#include "String.h"
|
||||||
|
|
||||||
class FileFormat{
|
class FileFormat{
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@ public:
|
||||||
Unknown
|
Unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
using ExtensionMap = std::map<Format, std::string>;
|
using ExtensionMap = Map<Format, String>;
|
||||||
public:
|
public:
|
||||||
static bool isFormat(const std::string& extension, Format format);
|
static bool isFormat(const String& extension, Format format);
|
||||||
|
|
||||||
static Format inferFormat(const std::string& query);
|
static Format inferFormat(const String& query);
|
||||||
|
|
||||||
static std::string getExtension(Format format);
|
static String getExtension(Format format);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ExtensionMap mExtensions;
|
static ExtensionMap mExtensions;
|
||||||
|
|
114
src/base/core/file_utilities/FileSystemPath.cpp
Normal file
114
src/base/core/file_utilities/FileSystemPath.cpp
Normal 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;
|
||||||
|
}
|
38
src/base/core/file_utilities/FileSystemPath.h
Normal file
38
src/base/core/file_utilities/FileSystemPath.h
Normal 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;
|
||||||
|
};
|
17
src/base/core/loggers/ConsoleLogger.cpp
Normal file
17
src/base/core/loggers/ConsoleLogger.cpp
Normal 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);
|
||||||
|
}
|
11
src/base/core/loggers/ConsoleLogger.h
Normal file
11
src/base/core/loggers/ConsoleLogger.h
Normal 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, ...);
|
||||||
|
};
|
|
@ -1,9 +1,20 @@
|
||||||
#include "FileLogger.h"
|
#include "FileLogger.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
FileLogger::FileLogger()
|
||||||
#include <filesystem>
|
:mWorkDirectory(),
|
||||||
|
mFileName("MT_Log.txt")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FileLogger& FileLogger::GetInstance()
|
||||||
|
{
|
||||||
|
static FileLogger instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
FileLogger::~FileLogger()
|
FileLogger::~FileLogger()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,33 +1,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define MLOG_ALL(msg, level) {std::ostringstream mt_logstream;\
|
#define MLOG_ALL(msg, level) {String mt_logstream;\
|
||||||
mt_logstream << msg; \
|
mt_logstream << msg; \
|
||||||
FileLogger::GetInstance().LogLine(level, mt_logstream, __FILE__, __FUNCTION__, __LINE__);};
|
FileLogger::GetInstance().LogLine(level, mt_logstream, __FILE__, __FUNCTION__, __LINE__);};
|
||||||
|
|
||||||
#define MLOG_INFO(msg) MLOG_ALL(msg, "Info");
|
#define MLOG_INFO(msg) MLOG_ALL(msg, "Info");
|
||||||
#define MLOG_ERROR(msg) MLOG_ALL(msg, "Error");
|
#define MLOG_ERROR(msg) MLOG_ALL(msg, "Error");
|
||||||
|
|
||||||
#include <memory>
|
#include "Pointer.h"
|
||||||
#include <string>
|
#include "String.h"
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
class FileLogger
|
class FileLogger
|
||||||
{
|
{
|
||||||
FileLogger()
|
FileLogger();
|
||||||
:mWorkDirectory(),
|
|
||||||
mFileName("MT_Log.txt"),
|
|
||||||
mFileStream()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static FileLogger& GetInstance()
|
static FileLogger& GetInstance();
|
||||||
{
|
|
||||||
static FileLogger instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileLogger(FileLogger const&) = delete;
|
FileLogger(FileLogger const&) = delete;
|
||||||
void operator=(FileLogger const&) = delete;
|
void operator=(FileLogger const&) = delete;
|
||||||
|
@ -36,22 +24,19 @@ public:
|
||||||
|
|
||||||
void disable();
|
void disable();
|
||||||
|
|
||||||
void SetWorkDirectory(const std::string& workDir);
|
void SetWorkDirectory(const String& workDir);
|
||||||
|
|
||||||
void SetFileName(const std::string& fileName);
|
void SetFileName(const String& fileName);
|
||||||
|
|
||||||
void Open();
|
void Open();
|
||||||
|
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
void LogLine(const std::ostringstream& line);
|
void LogLine(const String& line);
|
||||||
|
|
||||||
void LogLine(const std::string& logType, const std::ostringstream& line, const std::string& fileName = "", const std::string& functionName = "", int lineNumber=-1);
|
void LogLine(const String& logType, const String& line, const String& fileName = "", const String& functionName = "", int lineNumber=-1);
|
||||||
private:
|
private:
|
||||||
bool mDisabled{false};
|
bool mDisabled{false};
|
||||||
std::string mWorkDirectory;
|
String mWorkDirectory;
|
||||||
std::string mFileName;
|
String mFileName;
|
||||||
std::ofstream mFileStream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using FileLoggerPtr = std::shared_ptr<FileLogger>;
|
|
||||||
|
|
0
src/base/core/memory/Allocator.cpp
Normal file
0
src/base/core/memory/Allocator.cpp
Normal file
29
src/base/core/memory/Allocator.h
Normal file
29
src/base/core/memory/Allocator.h
Normal 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;
|
||||||
|
}
|
||||||
|
};
|
61
src/base/core/memory/Pointer.h
Normal file
61
src/base/core/memory/Pointer.h
Normal 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};
|
||||||
|
};
|
|
@ -2,15 +2,12 @@
|
||||||
|
|
||||||
#include "ByteUtils.h"
|
#include "ByteUtils.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
BitStream::~BitStream()
|
BitStream::~BitStream()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char BitStream::getCurrentByte()
|
Byte BitStream::getCurrentByte()
|
||||||
{
|
{
|
||||||
if (mByteOffset < 0)
|
if (mByteOffset < 0)
|
||||||
{
|
{
|
||||||
|
@ -19,19 +16,18 @@ unsigned char BitStream::getCurrentByte()
|
||||||
return mCurrentByte;
|
return mCurrentByte;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitStream::write(uint32_t data)
|
void BitStream::write(DWord data)
|
||||||
{
|
{
|
||||||
unsigned num_bytes = sizeof(uint32_t);
|
for(std::size_t idx=0; idx<sizeof(DWord); idx++)
|
||||||
for(unsigned idx=0; idx<num_bytes;idx++)
|
|
||||||
{
|
{
|
||||||
writeByte(ByteUtils::getByteN(data, idx));
|
writeByte(ByteUtils::getByteN(data, idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitStream::writeWord(uint16_t data)
|
void BitStream::writeWord(Word data)
|
||||||
{
|
{
|
||||||
const auto byte0 = static_cast<unsigned char>(data >> 8);
|
const auto byte0 = static_cast<Byte>(data >> 8);
|
||||||
const auto byte1 = static_cast<unsigned char>((data << 8) >> 8);
|
const auto byte1 = static_cast<Byte>((data << 8) >> 8);
|
||||||
writeByte(byte0);
|
writeByte(byte0);
|
||||||
writeByte(byte1);
|
writeByte(byte1);
|
||||||
}
|
}
|
||||||
|
@ -41,24 +37,26 @@ int BitStream::getCurrentByteOffset() const
|
||||||
return mByteOffset;
|
return mByteOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned BitStream::getCurrentBitOffset() const
|
std::size_t BitStream::getCurrentBitOffset() const
|
||||||
{
|
{
|
||||||
return mBitOffset;
|
return mBitOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BitStream::logLocation()
|
String BitStream::logLocation()
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
String ret;
|
||||||
sstr << "Byte offset " << mByteOffset<< " | Bit offset " << mBitOffset;
|
ret << "Byte offset " << mByteOffset<< " | Bit offset " << mBitOffset;
|
||||||
sstr << " | Working byte " << ByteUtils::toString(getCurrentByte()) << '\n';
|
ret << " | Working byte " << ByteUtils::toString(getCurrentByte()) << '\n';
|
||||||
return sstr.str();
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BitStream::logNextNBytes(unsigned n) const
|
String BitStream::logNextNBytes(std::size_t n) const
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
unsigned count{0};
|
std::size_t count{0};
|
||||||
for(auto byte : peekNextNBytes(n))
|
VecBytes bytes;
|
||||||
|
peekNextNBytes(n, bytes);
|
||||||
|
for(auto byte : bytes)
|
||||||
{
|
{
|
||||||
sstr << mByteOffset + count << " | " << ByteUtils::toString(byte) + '\n';
|
sstr << mByteOffset + count << " | " << ByteUtils::toString(byte) + '\n';
|
||||||
count++;
|
count++;
|
||||||
|
@ -66,28 +64,28 @@ std::string BitStream::logNextNBytes(unsigned n) const
|
||||||
return sstr.str();
|
return sstr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitStream::writeNBits(uint32_t data, unsigned length)
|
void BitStream::writeNBits(DWord data, std::size_t length)
|
||||||
{
|
{
|
||||||
const auto num_left = 8 - mBitOffset;
|
const auto num_left = 8 - mBitOffset;
|
||||||
const int overshoot = length - num_left;
|
const int overshoot = length - num_left;
|
||||||
|
|
||||||
if (overshoot > 0)
|
if (overshoot > 0)
|
||||||
{
|
{
|
||||||
unsigned char lower_bits = ByteUtils::getLowerNBits(data, num_left);
|
Byte lower_bits = ByteUtils::getLowerNBits(data, num_left);
|
||||||
mCurrentByte |= lower_bits << mBitOffset;
|
mCurrentByte |= lower_bits << mBitOffset;
|
||||||
|
|
||||||
writeByte(mCurrentByte, false);
|
writeByte(mCurrentByte, false);
|
||||||
|
|
||||||
unsigned num_bytes = overshoot / 8;
|
std::size_t num_bytes = overshoot / 8;
|
||||||
for (unsigned idx=0; idx< num_bytes; idx++)
|
for (std::size_t idx=0; idx< num_bytes; idx++)
|
||||||
{
|
{
|
||||||
mCurrentByte = ByteUtils::getMBitsAtN(static_cast<unsigned char>(data), overshoot, idx*8 + num_left);
|
mCurrentByte = ByteUtils::getMBitsAtN(static_cast<Byte>(data), overshoot, idx*8 + num_left);
|
||||||
writeByte(mCurrentByte, false);
|
writeByte(mCurrentByte, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto remainder = overshoot % 8; remainder > 0)
|
if (const auto remainder = overshoot % 8; remainder > 0)
|
||||||
{
|
{
|
||||||
mCurrentByte = ByteUtils::getMBitsAtN(static_cast<unsigned char>(data), remainder, num_bytes*8 + num_left);
|
mCurrentByte = ByteUtils::getMBitsAtN(static_cast<Byte>(data), remainder, num_bytes*8 + num_left);
|
||||||
mBitOffset = remainder;
|
mBitOffset = remainder;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -98,7 +96,7 @@ void BitStream::writeNBits(uint32_t data, unsigned length)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mCurrentByte |= (static_cast<unsigned char>(data) << mBitOffset);
|
mCurrentByte |= (static_cast<Byte>(data) << mBitOffset);
|
||||||
mBitOffset += length;
|
mBitOffset += length;
|
||||||
if (mBitOffset == 8)
|
if (mBitOffset == 8)
|
||||||
{
|
{
|
||||||
|
@ -107,10 +105,9 @@ void BitStream::writeNBits(uint32_t data, unsigned length)
|
||||||
mBitOffset = 0;
|
mBitOffset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitStream::readNextNBits(unsigned n, unsigned char& buffer)
|
bool BitStream::readNextNBits(std::size_t n, Byte& buffer)
|
||||||
{
|
{
|
||||||
if (mByteOffset < 0)
|
if (mByteOffset < 0)
|
||||||
{
|
{
|
||||||
|
@ -123,15 +120,15 @@ bool BitStream::readNextNBits(unsigned n, unsigned char& buffer)
|
||||||
int overshoot = n + mBitOffset - 8;
|
int overshoot = n + mBitOffset - 8;
|
||||||
if (overshoot > 0)
|
if (overshoot > 0)
|
||||||
{
|
{
|
||||||
unsigned char last_byte = mCurrentByte;
|
const auto last_byte = mCurrentByte;
|
||||||
if (!readNextByte())
|
if (!readNextByte())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto num_lower = 8 - mBitOffset;
|
auto num_lower = 8 - mBitOffset;
|
||||||
char lower_bits = ByteUtils::getHigherNBits(last_byte, num_lower);
|
const auto lower_bits = ByteUtils::getHigherNBits(last_byte, num_lower);
|
||||||
char higher_bits = ByteUtils::getLowerNBits(mCurrentByte, overshoot);
|
const auto higher_bits = ByteUtils::getLowerNBits(mCurrentByte, overshoot);
|
||||||
|
|
||||||
buffer = (higher_bits << num_lower) | lower_bits;
|
buffer = (higher_bits << num_lower) | lower_bits;
|
||||||
|
|
||||||
|
@ -145,3 +142,44 @@ bool BitStream::readNextNBits(unsigned n, unsigned char& buffer)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BitStream::resetOffsets()
|
||||||
|
{
|
||||||
|
mEndByteOffset = mByteOffset;
|
||||||
|
mEndBitOffset = mBitOffset;
|
||||||
|
mEndByte = mCurrentByte;
|
||||||
|
|
||||||
|
mCurrentByte = 0;
|
||||||
|
mByteOffset = -1;
|
||||||
|
mBitOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitStream::reset()
|
||||||
|
{
|
||||||
|
resetOffsets();
|
||||||
|
mCurrentByte = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitStream::flushRemainingBits()
|
||||||
|
{
|
||||||
|
if (mBitOffset > 0)
|
||||||
|
{
|
||||||
|
writeByte(mCurrentByte, false);
|
||||||
|
mBitOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<Byte, std::size_t> BitStream::getRemainingBits() const
|
||||||
|
{
|
||||||
|
return {mEndByte, mEndBitOffset};
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitStream::setChecksumCalculator(AbstractChecksumCalculator* calc)
|
||||||
|
{
|
||||||
|
mChecksumCalculator = calc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitStream::clearChecksumCalculator()
|
||||||
|
{
|
||||||
|
mChecksumCalculator = nullptr;
|
||||||
|
}
|
||||||
|
|
|
@ -1,92 +1,63 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AbstractChecksumCalculator.h"
|
#include "AbstractChecksumCalculator.h"
|
||||||
|
#include "ByteTypes.h"
|
||||||
#include <vector>
|
#include "String.h"
|
||||||
#include <string>
|
#include "Optional.h"
|
||||||
#include <optional>
|
#include "Pair.h"
|
||||||
|
|
||||||
class BitStream
|
class BitStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~BitStream();
|
virtual ~BitStream();
|
||||||
|
|
||||||
unsigned char getCurrentByte();
|
Byte getCurrentByte();
|
||||||
|
|
||||||
int getCurrentByteOffset() const;
|
int getCurrentByteOffset() const;
|
||||||
|
|
||||||
unsigned getCurrentBitOffset() const;
|
std::size_t getCurrentBitOffset() const;
|
||||||
|
|
||||||
virtual bool isFinished() const = 0;
|
virtual bool isFinished() const = 0;
|
||||||
|
|
||||||
std::string logNextNBytes(unsigned n) const;
|
String logNextNBytes(std::size_t n) const;
|
||||||
|
|
||||||
std::string logLocation();
|
String logLocation();
|
||||||
|
|
||||||
virtual std::vector<unsigned char> peekNextNBytes(unsigned n) const = 0;
|
virtual void peekNextNBytes(std::size_t n, VecBytes& bytes) const = 0;
|
||||||
|
|
||||||
virtual bool readNextNBits(unsigned n, unsigned char& buffer);
|
virtual bool readNextNBits(std::size_t n, Byte& buffer);
|
||||||
|
|
||||||
virtual std::optional<unsigned char> readNextByte() = 0;
|
virtual Optional<Byte> readNextByte() = 0;
|
||||||
|
|
||||||
virtual void writeNBits(uint32_t data, unsigned length);
|
virtual void writeNBits(DWord data, std::size_t length);
|
||||||
|
|
||||||
virtual void writeByte(unsigned char data, bool checkOverflow = true) = 0;
|
virtual void writeByte(Byte data, bool checkOverflow = true) = 0;
|
||||||
|
|
||||||
void write(uint32_t data);
|
void write(DWord data);
|
||||||
|
|
||||||
void writeWord(uint16_t data);
|
void writeWord(Word data);
|
||||||
|
|
||||||
virtual void writeBytes(const std::vector<unsigned char> data) = 0;
|
virtual void writeBytes(const VecBytes& data) = 0;
|
||||||
|
|
||||||
void resetOffsets()
|
void resetOffsets();
|
||||||
{
|
|
||||||
mEndByteOffset = mByteOffset;
|
|
||||||
mEndBitOffset = mBitOffset;
|
|
||||||
mEndByte = mCurrentByte;
|
|
||||||
|
|
||||||
mCurrentByte = 0;
|
virtual void reset();
|
||||||
mByteOffset = -1;
|
|
||||||
mBitOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void reset()
|
void flushRemainingBits();
|
||||||
{
|
|
||||||
resetOffsets();
|
|
||||||
mCurrentByte = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flushRemainingBits()
|
Pair<Byte, std::size_t> getRemainingBits() const;
|
||||||
{
|
|
||||||
if (mBitOffset > 0)
|
|
||||||
{
|
|
||||||
writeByte(mCurrentByte, false);
|
|
||||||
mBitOffset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<unsigned char, unsigned> getRemainingBits() const
|
void setChecksumCalculator(AbstractChecksumCalculator* calc);
|
||||||
{
|
|
||||||
return {mEndByte, mEndBitOffset};
|
|
||||||
}
|
|
||||||
|
|
||||||
void setChecksumCalculator(AbstractChecksumCalculator* calc)
|
void clearChecksumCalculator();
|
||||||
{
|
|
||||||
mChecksumCalculator = calc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearChecksumCalculator()
|
|
||||||
{
|
|
||||||
mChecksumCalculator = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int mByteOffset{-1};
|
int mByteOffset{-1};
|
||||||
unsigned mBitOffset{0};
|
std::size_t mBitOffset{0};
|
||||||
unsigned char mCurrentByte{0};
|
Byte mCurrentByte{0};
|
||||||
|
|
||||||
int mEndByteOffset{-1};
|
int mEndByteOffset{-1};
|
||||||
unsigned mEndBitOffset{0};
|
std::size_t mEndBitOffset{0};
|
||||||
unsigned char mEndByte{0};
|
Byte mEndByte{0};
|
||||||
AbstractChecksumCalculator* mChecksumCalculator{nullptr};
|
AbstractChecksumCalculator* mChecksumCalculator{nullptr};
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,10 +9,10 @@ bool BufferBitStream::isFinished() const
|
||||||
return mByteOffset == static_cast<int>(mBuffer.size()) - 1;
|
return mByteOffset == static_cast<int>(mBuffer.size()) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> BufferBitStream::peekNextNBytes(unsigned n) const
|
void BufferBitStream::peekNextNBytes(std::size_t n, VecBytes& ret) const
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> ret (n, 0);
|
ret.resize(n, 0);
|
||||||
unsigned count = 0;
|
std::size_t count = 0;
|
||||||
|
|
||||||
int start = mByteOffset;
|
int start = mByteOffset;
|
||||||
if (start<0)
|
if (start<0)
|
||||||
|
@ -28,12 +28,11 @@ std::vector<unsigned char> BufferBitStream::peekNextNBytes(unsigned n) const
|
||||||
}
|
}
|
||||||
|
|
||||||
ret[count] = mBuffer[idx];
|
ret[count] = mBuffer[idx];
|
||||||
count ++;
|
count++;
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<unsigned char> BufferBitStream::readNextByte()
|
std::optional<uint8_t> BufferBitStream::readNextByte()
|
||||||
{
|
{
|
||||||
if (mByteOffset + 1 == static_cast<int>(mBuffer.size()))
|
if (mByteOffset + 1 == static_cast<int>(mBuffer.size()))
|
||||||
{
|
{
|
||||||
|
@ -47,14 +46,14 @@ std::optional<unsigned char> BufferBitStream::readNextByte()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBitStream::setBuffer(const std::vector<unsigned char>& data)
|
void BufferBitStream::setBuffer(const VecBytes& data)
|
||||||
{
|
{
|
||||||
mBuffer = data;
|
mBuffer = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBitStream::writeByte(unsigned char data, bool checkOverflow)
|
void BufferBitStream::writeByte(uint8_t data, bool checkOverflow)
|
||||||
{
|
{
|
||||||
unsigned char out_byte{0};
|
uint8_t out_byte{0};
|
||||||
if (checkOverflow && mBitOffset > 0)
|
if (checkOverflow && mBitOffset > 0)
|
||||||
{
|
{
|
||||||
out_byte = ByteUtils::getLowerNBits(mCurrentByte, mBitOffset);
|
out_byte = ByteUtils::getLowerNBits(mCurrentByte, mBitOffset);
|
||||||
|
@ -76,12 +75,12 @@ void BufferBitStream::writeByte(unsigned char data, bool checkOverflow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BufferBitStream::writeBytes(const std::vector<unsigned char> data)
|
void BufferBitStream::writeBytes(const VecBytes& data)
|
||||||
{
|
{
|
||||||
std::copy(data.begin(), data.end(), std::back_inserter(mBuffer));
|
std::copy(data.begin(), data.end(), std::back_inserter(mBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<unsigned char>& BufferBitStream::getBuffer() const
|
const VecBytes& BufferBitStream::getBuffer() const
|
||||||
{
|
{
|
||||||
return mBuffer;
|
return mBuffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,28 +2,25 @@
|
||||||
|
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
class BufferBitStream : public BitStream
|
class BufferBitStream : public BitStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const std::vector<unsigned char>& getBuffer() const;
|
const VecBytes& getBuffer() const;
|
||||||
|
|
||||||
bool isFinished() const override;
|
bool isFinished() const override;
|
||||||
|
|
||||||
std::vector<unsigned char> peekNextNBytes(unsigned n) const override;
|
void peekNextNBytes(std::size_t n, VecBytes& bytes) const override;
|
||||||
|
|
||||||
std::optional<unsigned char> readNextByte() override;
|
std::optional<uint8_t> readNextByte() override;
|
||||||
|
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
void setBuffer(const std::vector<unsigned char>& data);
|
void setBuffer(const VecBytes& data);
|
||||||
|
|
||||||
void writeByte(unsigned char data, bool checkOverflow = true) override;
|
void writeByte(uint8_t data, bool checkOverflow = true) override;
|
||||||
|
|
||||||
void writeBytes(const std::vector<unsigned char> data) override;
|
void writeBytes(const VecBytes& data) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<unsigned char> mBuffer;
|
VecBytes mBuffer;
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,16 +12,15 @@ bool InputBitStream::isFinished() const
|
||||||
return mStream->good();
|
return mStream->good();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> InputBitStream::peekNextNBytes(unsigned) const
|
void InputBitStream::peekNextNBytes(std::size_t, VecBytes&) const
|
||||||
{
|
{
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<unsigned char> InputBitStream::readNextByte()
|
std::optional<Byte> InputBitStream::readNextByte()
|
||||||
{
|
{
|
||||||
if (mStream->good())
|
if (mStream->good())
|
||||||
{
|
{
|
||||||
return static_cast<unsigned char>(mStream->get());
|
return static_cast<Byte>(mStream->get());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -29,7 +28,7 @@ std::optional<unsigned char> InputBitStream::readNextByte()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputBitStream::writeByte(unsigned char, bool)
|
void InputBitStream::writeByte(Byte, bool)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,13 @@ class InputBitStream : public BitStream
|
||||||
|
|
||||||
bool isFinished() const override;
|
bool isFinished() const override;
|
||||||
|
|
||||||
std::vector<unsigned char> peekNextNBytes(unsigned n) const override;
|
void peekNextNBytes(std::size_t n, VecBytes& bytes) const override;
|
||||||
|
|
||||||
std::optional<unsigned char> readNextByte() override;
|
std::optional<Byte> readNextByte() override;
|
||||||
|
|
||||||
void writeByte(unsigned char data, bool checkOverflow = true) override;
|
void writeByte(Byte data, bool checkOverflow = true) override;
|
||||||
|
|
||||||
void writeBytes(const std::vector<unsigned char>) override
|
void writeBytes(const VecBytes&) override
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,22 +12,22 @@ bool OutputBitStream::isFinished() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> OutputBitStream::peekNextNBytes(unsigned) const
|
void OutputBitStream::peekNextNBytes(std::size_t, VecBytes&) const
|
||||||
{
|
{
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<unsigned char> OutputBitStream::readNextByte()
|
std::optional<uint8_t> OutputBitStream::readNextByte()
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputBitStream::writeByte(unsigned char data, bool)
|
void OutputBitStream::writeByte(uint8_t data, bool)
|
||||||
{
|
{
|
||||||
(*mStream) << data;
|
(*mStream) << data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputBitStream::writeBytes(const std::vector<unsigned char> data)
|
void OutputBitStream::writeBytes(const VecBytes& data)
|
||||||
{
|
{
|
||||||
for(auto byte : data)
|
for(auto byte : data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,13 +11,13 @@ public:
|
||||||
|
|
||||||
bool isFinished() const override;
|
bool isFinished() const override;
|
||||||
|
|
||||||
std::vector<unsigned char> peekNextNBytes(unsigned n) const override;
|
void peekNextNBytes(std::size_t n, VecBytes& bytes) const override;
|
||||||
|
|
||||||
std::optional<unsigned char> readNextByte() override;
|
std::optional<Byte> readNextByte() override;
|
||||||
|
|
||||||
void writeByte(unsigned char data, bool checkOverflow = true) override;
|
void writeByte(Byte data, bool checkOverflow = true) override;
|
||||||
|
|
||||||
void writeBytes(const std::vector<unsigned char> data) override;
|
void writeBytes(const VecBytes& data) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::basic_ostream<char>* mStream{nullptr};
|
std::basic_ostream<char>* mStream{nullptr};
|
||||||
|
|
|
@ -12,7 +12,7 @@ public:
|
||||||
this->mData->initializeTo(numPointsX * numPointsY * numPointsZ, T());
|
this->mData->initializeTo(numPointsX * numPointsY * numPointsZ, T());
|
||||||
}
|
}
|
||||||
|
|
||||||
T getItem(std::size_t idx, std::size_t jdx, std::size_t kdx) const override
|
T getItem(std::size_t idx, std::size_t jdx, std::size_t kdx = 1) const override
|
||||||
{
|
{
|
||||||
return this->mData->getItem(getOffset(idx, jdx, kdx));
|
return this->mData->getItem(getOffset(idx, jdx, kdx));
|
||||||
}
|
}
|
||||||
|
@ -37,3 +37,40 @@ public:
|
||||||
return this->mData->getLength();
|
return this->mData->getLength();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class SerializeableGrid : public Grid<T>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SerializeableGrid(std::size_t itemSize, const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, std::size_t numPointsZ = 1)
|
||||||
|
: Grid<T>(bounds, numPointsX, numPointsY, numPointsZ),
|
||||||
|
mItemSize(itemSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getByte(std::size_t index)
|
||||||
|
{
|
||||||
|
const auto item_index = index/mItemSize;
|
||||||
|
const auto item_internal_index = index % mItemSize;
|
||||||
|
return this->mData->getItem(item_index).getByte(item_internal_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toBuffer(uint8_t* buffer, std::size_t bufferMaxSize)
|
||||||
|
{
|
||||||
|
std::size_t count{0};
|
||||||
|
std::size_t item_count{0};
|
||||||
|
while(count < bufferMaxSize && item_count < this->mData->getLength())
|
||||||
|
{
|
||||||
|
const auto& item = this->mData->getItem(item_count);
|
||||||
|
for(std::size_t idx = 0; idx< item.getSize(); idx++)
|
||||||
|
{
|
||||||
|
buffer[count] = item.getByte(idx);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
item_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t mItemSize{1};
|
||||||
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@ list(APPEND HEADERS
|
||||||
BasicWebApp.h)
|
BasicWebApp.h)
|
||||||
|
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
|
TermInfo.cpp
|
||||||
BasicWebApp.cpp
|
BasicWebApp.cpp
|
||||||
MainApplication.cpp)
|
MainApplication.cpp)
|
||||||
|
|
||||||
|
|
111
src/console/TermInfo.cpp
Normal file
111
src/console/TermInfo.cpp
Normal 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
17
src/console/TermInfo.h
Normal 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
43
src/main.cpp
Normal 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;
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ set(platform_LIB_INCLUDES)
|
||||||
|
|
||||||
list(APPEND image_HEADERS
|
list(APPEND image_HEADERS
|
||||||
Image.h
|
Image.h
|
||||||
|
Pixel.h
|
||||||
IImageWriter.h
|
IImageWriter.h
|
||||||
PlatformImage.h
|
PlatformImage.h
|
||||||
PlatformImageWriter.h
|
PlatformImageWriter.h
|
||||||
|
@ -14,6 +15,7 @@ list(APPEND image_HEADERS
|
||||||
|
|
||||||
list(APPEND image_LIB_INCLUDES
|
list(APPEND image_LIB_INCLUDES
|
||||||
Image.cpp
|
Image.cpp
|
||||||
|
Pixel.cpp
|
||||||
ImageBitStream.cpp
|
ImageBitStream.cpp
|
||||||
PlatformImage.cpp
|
PlatformImage.cpp
|
||||||
png/BasicPngWriter.cpp
|
png/BasicPngWriter.cpp
|
||||||
|
@ -21,6 +23,7 @@ list(APPEND image_LIB_INCLUDES
|
||||||
png/PngReader.cpp
|
png/PngReader.cpp
|
||||||
png/PngHeader.cpp
|
png/PngHeader.cpp
|
||||||
png/PngInfo.cpp
|
png/PngInfo.cpp
|
||||||
|
png/PngFilter.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
|
|
@ -3,14 +3,16 @@
|
||||||
#include "Color.h"
|
#include "Color.h"
|
||||||
#include "Grid.h"
|
#include "Grid.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "Win32WicImage.h"
|
#include "Win32WicImage.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Image::Image(unsigned width, unsigned height, DataType dataType)
|
Image::Image(unsigned width, unsigned height, Color::Format format)
|
||||||
: mWidth(width),
|
: mWidth(width),
|
||||||
mHeight(height),
|
mHeight(height),
|
||||||
mDataType(dataType)
|
mFormat(format)
|
||||||
{
|
{
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
@ -20,49 +22,37 @@ Image::~Image()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Image> Image::Create(unsigned width, unsigned height, DataType dataType)
|
std::unique_ptr<Image> Image::Create(unsigned width, unsigned height, Color::Format format)
|
||||||
{
|
{
|
||||||
return std::make_unique<Image>(width, height, dataType);
|
return std::make_unique<Image>(width, height, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::initialize()
|
void Image::initialize()
|
||||||
{
|
{
|
||||||
Bounds bounds(0.0, mWidth, 0.0, mHeight);
|
Bounds bounds(0.0, mWidth, 0.0, mHeight);
|
||||||
if (mDataType == DataType::UCHAR)
|
const auto pixel_size = Color::getSize(mFormat, mBitDepth);
|
||||||
{
|
mGrid = std::make_unique<SerializeableGrid<Pixel> >(pixel_size, bounds, mWidth, mHeight);
|
||||||
mData = std::make_unique<Grid<unsigned char> >(bounds, mWidth, mHeight, mNumChannels);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mData = std::make_unique<Grid<uint8_t> >(bounds, mWidth, mHeight, mNumChannels);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::setPixelValues(const Indices& indices, const std::vector<Color>& colors)
|
void Image::setPixelValues(const Indices& indices, const std::vector<Color>& colors)
|
||||||
{
|
{
|
||||||
if (!mData)
|
if (!mGrid)
|
||||||
{
|
{
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDataType == DataType::UCHAR)
|
assert(indices.size() == colors.size());
|
||||||
{
|
|
||||||
auto grid = getGridT<unsigned char>();
|
|
||||||
for (std::size_t idx=0; idx< indices.size(); idx++)
|
for (std::size_t idx=0; idx< indices.size(); idx++)
|
||||||
{
|
{
|
||||||
auto id = indices[idx];
|
const auto id = indices[idx];
|
||||||
auto color = colors[idx];
|
mGrid->getItem(id.first, id.second).setColor(colors[idx]);
|
||||||
grid->setItem(id.first, id.second, 0, color.getR());
|
|
||||||
grid->setItem(id.first, id.second, 1, color.getG());
|
|
||||||
grid->setItem(id.first, id.second, 2, color.getB());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Image::getBytesPerRow() const
|
unsigned Image::getBytesPerRow() const
|
||||||
{
|
{
|
||||||
const auto bitsPerEntry = mBitDepth <= 8 ? 1 : 2;
|
return mWidth * Color::getSize(mFormat, mBitDepth);
|
||||||
return mWidth * mNumChannels * bitsPerEntry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Image::getWidth() const
|
unsigned Image::getWidth() const
|
||||||
|
@ -91,25 +81,29 @@ PlatformImage* Image::getPlatformImage()
|
||||||
return mPlatformImage.get();
|
return mPlatformImage.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractGrid* Image::getGrid() const
|
SerializeableGrid<Pixel>* Image::getGrid() const
|
||||||
{
|
{
|
||||||
return mData.get();
|
return mGrid.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
uint8_t Image::getByte(std::size_t index) const
|
||||||
Grid<T>* Image::getGridT() const
|
|
||||||
{
|
{
|
||||||
return dynamic_cast<Grid<T>*>(this->mData.get());
|
return mGrid->getByte(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::DataType Image::getType() const
|
void Image::toBuffer(uint8_t* buffer, std::size_t bufferMaxSize)
|
||||||
{
|
{
|
||||||
return mDataType;
|
mGrid->toBuffer(buffer, bufferMaxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color::Format Image::getFormat() const
|
||||||
|
{
|
||||||
|
return mFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Image::getNumChannels() const
|
unsigned Image::getNumChannels() const
|
||||||
{
|
{
|
||||||
return mNumChannels;
|
return Color::getNumChannels(mFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::setWidth(unsigned width)
|
void Image::setWidth(unsigned width)
|
||||||
|
@ -127,8 +121,8 @@ void Image::setBitDepth(unsigned bitDepth)
|
||||||
mBitDepth = bitDepth;
|
mBitDepth = bitDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::setNumChannels(unsigned numChannels)
|
void Image::setFormat(Color::Format format)
|
||||||
{
|
{
|
||||||
mNumChannels = numChannels;
|
mFormat = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,25 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "PlatformImage.h"
|
#include "PlatformImage.h"
|
||||||
|
#include "Pixel.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Color;
|
class Color;
|
||||||
|
|
||||||
class AbstractGrid;
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Grid;
|
class SerializeableGrid;
|
||||||
|
|
||||||
class Image
|
class Image
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class DataType
|
|
||||||
{
|
|
||||||
UCHAR
|
|
||||||
};
|
|
||||||
|
|
||||||
using Index = std::pair<std::size_t, std::size_t>;
|
using Index = std::pair<std::size_t, std::size_t>;
|
||||||
using Indices = std::vector<Index>;
|
using Indices = std::vector<Index>;
|
||||||
|
|
||||||
Image(unsigned width, unsigned height, DataType dataType = DataType::UCHAR);
|
Image(unsigned width, unsigned height, Color::Format format = Color::Format::RGBA);
|
||||||
~Image();
|
~Image();
|
||||||
static std::unique_ptr<Image> Create(unsigned width, unsigned height, DataType dataType = DataType::UCHAR);
|
static std::unique_ptr<Image> Create(unsigned width, unsigned height, Color::Format format = Color::Format::RGBA);
|
||||||
|
|
||||||
unsigned getBytesPerRow() const;
|
unsigned getBytesPerRow() const;
|
||||||
unsigned getWidth() const;
|
unsigned getWidth() const;
|
||||||
|
@ -32,28 +27,27 @@ public:
|
||||||
unsigned getBitDepth() const;
|
unsigned getBitDepth() const;
|
||||||
unsigned getNumChannels() const;
|
unsigned getNumChannels() const;
|
||||||
|
|
||||||
AbstractGrid* getGrid() const;
|
uint8_t getByte(std::size_t index) const;
|
||||||
|
SerializeableGrid<Pixel>* getGrid() const;
|
||||||
|
|
||||||
template<typename T>
|
Color::Format getFormat() const;
|
||||||
Grid<T>* getGridT() const;
|
|
||||||
|
|
||||||
DataType getType() const;
|
|
||||||
PlatformImage* getPlatformImage();
|
PlatformImage* getPlatformImage();
|
||||||
|
|
||||||
void setPixelValues(const Indices& indices, const std::vector<Color>& colors);
|
void setPixelValues(const Indices& indices, const std::vector<Color>& colors);
|
||||||
void setWidth(unsigned width);
|
void setWidth(unsigned width);
|
||||||
void setHeight(unsigned height);
|
void setHeight(unsigned height);
|
||||||
void setBitDepth(unsigned bitDepth);
|
void setBitDepth(unsigned bitDepth);
|
||||||
void setNumChannels(unsigned numChannels);
|
void setFormat(Color::Format format);
|
||||||
|
|
||||||
|
void toBuffer(uint8_t* buffer, std::size_t bufferMaxSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialize();
|
void initialize();
|
||||||
unsigned mWidth{1};
|
unsigned mWidth{1};
|
||||||
unsigned mHeight{1};
|
unsigned mHeight{1};
|
||||||
unsigned mBitDepth{8};
|
unsigned mBitDepth{8};
|
||||||
unsigned mNumChannels{4};
|
Color::Format mFormat{Color::Format::RGBA};
|
||||||
|
|
||||||
DataType mDataType;
|
std::unique_ptr<SerializeableGrid<Pixel> > mGrid;
|
||||||
std::unique_ptr<AbstractGrid> mData;
|
|
||||||
std::unique_ptr<PlatformImage> mPlatformImage;
|
std::unique_ptr<PlatformImage> mPlatformImage;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "ImageBitStream.h"
|
#include "ImageBitStream.h"
|
||||||
|
|
||||||
#include "AbstractGrid.h"
|
#include "Grid.h"
|
||||||
|
#include "Pixel.h"
|
||||||
|
|
||||||
ImageBitStream::ImageBitStream(Image* image)
|
ImageBitStream::ImageBitStream(Image* image)
|
||||||
: BitStream(),
|
: BitStream(),
|
||||||
|
@ -14,25 +15,22 @@ bool ImageBitStream::isFinished() const
|
||||||
return mByteOffset == static_cast<int>(mImage->getGrid()->getDataSize());
|
return mByteOffset == static_cast<int>(mImage->getGrid()->getDataSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> ImageBitStream::peekNextNBytes(unsigned) const
|
std::vector<uint8_t> ImageBitStream::peekNextNBytes(std::size_t) const
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<unsigned char> ImageBitStream::readNextByte()
|
std::optional<uint8_t> ImageBitStream::readNextByte()
|
||||||
{
|
{
|
||||||
mByteOffset++;
|
mByteOffset++;
|
||||||
|
|
||||||
if (isFinished() )
|
if (isFinished() )
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
//const auto val = mImage->getData()->getAsUnsignedChar(mByteOffset);
|
return mImage->getByte(mByteOffset);
|
||||||
//return val;
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageBitStream::writeByte(unsigned char, bool )
|
void ImageBitStream::writeByte(uint8_t, bool )
|
||||||
{
|
{
|
||||||
mByteOffset++;
|
mByteOffset++;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
class ImageBitStream : public BitStream
|
class ImageBitStream : public BitStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -11,13 +13,13 @@ public:
|
||||||
|
|
||||||
bool isFinished() const override;
|
bool isFinished() const override;
|
||||||
|
|
||||||
std::vector<unsigned char> peekNextNBytes(unsigned n) const override;
|
std::vector<uint8_t> peekNextNBytes(std::size_t n) const override;
|
||||||
|
|
||||||
std::optional<unsigned char> readNextByte() override;
|
std::optional<uint8_t> readNextByte() override;
|
||||||
|
|
||||||
void writeByte(unsigned char data, bool checkOverflow = true) override;
|
void writeByte(uint8_t data, bool checkOverflow = true) override;
|
||||||
|
|
||||||
void writeBytes(const std::vector<unsigned char>) override
|
void writeBytes(const std::vector<uint8_t>&) override
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
0
src/media/image/Pixel.cpp
Normal file
0
src/media/image/Pixel.cpp
Normal file
26
src/media/image/Pixel.h
Normal file
26
src/media/image/Pixel.h
Normal 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;
|
||||||
|
};
|
|
@ -88,13 +88,13 @@ void BasicPngWriter::writeHeader()
|
||||||
|
|
||||||
auto crc = mPngHeader.getCrc();
|
auto crc = mPngHeader.getCrc();
|
||||||
|
|
||||||
//std::cout << mPngHeader.toString() << "*********" << std::endl;
|
std::cout << mPngHeader.toString() << "*********" << std::endl;
|
||||||
mOutStream->write(crc);
|
mOutStream->write(crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicPngWriter::writeEndChunk()
|
void BasicPngWriter::writeEndChunk()
|
||||||
{
|
{
|
||||||
//std::cout << "Start writing end chunk" << std::endl;
|
std::cout << "Start writing end chunk" << std::endl;
|
||||||
unsigned length{ 0 };
|
unsigned length{ 0 };
|
||||||
mOutStream->write(length);
|
mOutStream->write(length);
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ void BasicPngWriter::writeEndChunk()
|
||||||
auto crc = crc_check.getChecksum();
|
auto crc = crc_check.getChecksum();
|
||||||
mOutStream->write(crc);
|
mOutStream->write(crc);
|
||||||
|
|
||||||
//std::cout << "Writing end chunk" << std::endl;
|
std::cout << "Finishe Writing end chunk" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer)
|
void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer)
|
||||||
|
@ -128,7 +128,7 @@ void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer)
|
||||||
}
|
}
|
||||||
(void)length;
|
(void)length;
|
||||||
|
|
||||||
//std::cout << "Writing idat length " << num_bytes << std::endl;
|
std::cout << "Writing idat length " << num_bytes << std::endl;
|
||||||
mOutStream->write(static_cast<uint32_t>(num_bytes));
|
mOutStream->write(static_cast<uint32_t>(num_bytes));
|
||||||
|
|
||||||
std::vector<unsigned char> char_data = StringUtils::toBytes("IDAT");
|
std::vector<unsigned char> char_data = StringUtils::toBytes("IDAT");
|
||||||
|
@ -148,7 +148,7 @@ void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto crc = crc_check.getChecksum();
|
auto crc = crc_check.getChecksum();
|
||||||
//std::cout << "Writing idat crc" << crc << std::endl;
|
std::cout << "Writing idat crc: " << crc << std::endl;
|
||||||
mOutStream->write(crc);
|
mOutStream->write(crc);
|
||||||
//std::cout << "Finished Writing idat crc" << crc << std::endl;
|
//std::cout << "Finished Writing idat crc" << crc << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ void BasicPngWriter::write(const Path& path, Image* image)
|
||||||
{
|
{
|
||||||
std::unique_ptr<File> out_file;
|
std::unique_ptr<File> out_file;
|
||||||
|
|
||||||
if (path.empty())
|
if (!path.empty())
|
||||||
{
|
{
|
||||||
out_file = std::make_unique<File>(path);
|
out_file = std::make_unique<File>(path);
|
||||||
out_file->open(File::AccessMode::Write);
|
out_file->open(File::AccessMode::Write);
|
||||||
|
|
|
@ -22,7 +22,9 @@ public:
|
||||||
|
|
||||||
virtual ~BasicPngWriter();
|
virtual ~BasicPngWriter();
|
||||||
|
|
||||||
static std::unique_ptr<BasicPngWriter> Create();
|
using Ptr = std::unique_ptr<BasicPngWriter>;
|
||||||
|
|
||||||
|
static BasicPngWriter::Ptr Create();
|
||||||
|
|
||||||
void setCompressionMethod(Deflate::CompressionMethod method);
|
void setCompressionMethod(Deflate::CompressionMethod method);
|
||||||
|
|
||||||
|
@ -44,7 +46,7 @@ private:
|
||||||
std::unique_ptr<BitStream> mInStream;
|
std::unique_ptr<BitStream> mInStream;
|
||||||
std::unique_ptr<BitStream> mOutStream;
|
std::unique_ptr<BitStream> mOutStream;
|
||||||
|
|
||||||
unsigned mPngInfoUserSet{ false };
|
bool mPngInfoUserSet{ false };
|
||||||
PngInfo mPngInfo;
|
PngInfo mPngInfo;
|
||||||
PngHeader mPngHeader;
|
PngHeader mPngHeader;
|
||||||
|
|
||||||
|
|
77
src/media/image/png/PngFilter.cpp
Normal file
77
src/media/image/png/PngFilter.cpp
Normal 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++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,83 +19,13 @@ public:
|
||||||
PAETH
|
PAETH
|
||||||
};
|
};
|
||||||
|
|
||||||
PngFilter(BitStream* inputStream, BitStream* outputStream)
|
PngFilter(BitStream* inputStream, BitStream* outputStream);
|
||||||
: mInputStream(inputStream),
|
|
||||||
mOutputStream(outputStream)
|
|
||||||
|
|
||||||
{
|
void encode();
|
||||||
|
|
||||||
}
|
void decode();
|
||||||
|
|
||||||
void encode()
|
|
||||||
{
|
|
||||||
auto image_stream = dynamic_cast<ImageBitStream*>(mInputStream);
|
|
||||||
if (!image_stream)
|
|
||||||
{
|
|
||||||
MLOG_ERROR("Expected ImageStream in PngFilter encode - aborting.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto bytes_per_scanline = image_stream->getBytesPerScanline();
|
|
||||||
unsigned count{0};
|
|
||||||
if (mFilterType == FilterType::NONE)
|
|
||||||
{
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
if (const auto byte = image_stream->readNextByte())
|
|
||||||
{
|
|
||||||
if (count % bytes_per_scanline == 0)
|
|
||||||
{
|
|
||||||
mOutputStream->writeByte(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
mOutputStream->writeByte(*byte);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void decode()
|
|
||||||
{
|
|
||||||
auto image_stream = dynamic_cast<ImageBitStream*>(mOutputStream);
|
|
||||||
if (!image_stream)
|
|
||||||
{
|
|
||||||
MLOG_ERROR("Expected ImageStream in PngFilter decode - aborting.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto bytes_per_scanline = image_stream->getBytesPerScanline();
|
|
||||||
unsigned count{0};
|
|
||||||
|
|
||||||
FilterType working_filter_type = FilterType::NONE;
|
|
||||||
while(auto byte = mInputStream->readNextByte())
|
|
||||||
{
|
|
||||||
if (count % bytes_per_scanline == 0)
|
|
||||||
{
|
|
||||||
working_filter_type = static_cast<FilterType>(*byte);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (working_filter_type == FilterType::NONE)
|
|
||||||
{
|
|
||||||
image_stream->writeByte(*byte);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//std::cout << "Got filter type " << static_cast<int>(working_filter_type) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
FilterType mFilterType{FilterType::NONE};
|
FilterType mFilterType{FilterType::NONE};
|
||||||
BitStream* mInputStream{nullptr};
|
BitStream* mInputStream{nullptr};
|
||||||
BitStream* mOutputStream{nullptr};
|
BitStream* mOutputStream{nullptr};
|
||||||
|
|
|
@ -10,26 +10,46 @@ std::string PngHeader::toString() const
|
||||||
sstr << "PngHeader" << "\n";
|
sstr << "PngHeader" << "\n";
|
||||||
sstr << "width: " << mWidth << "\n";
|
sstr << "width: " << mWidth << "\n";
|
||||||
sstr << "height: " << mHeight << "\n";
|
sstr << "height: " << mHeight << "\n";
|
||||||
sstr << "bitDepth: " << (int)mBitDepth << "\n";
|
sstr << "bitDepth: " << static_cast<int>(mBitDepth) << "\n";
|
||||||
sstr << "cached CRC: " << mCachedCrc << "\n";
|
sstr << "cached CRC: " << mCachedCrc << "\n";
|
||||||
|
|
||||||
sstr << mPngInfo.toString();
|
sstr << mPngInfo.toString();
|
||||||
return sstr.str();
|
return sstr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t PngHeader::getLength() const
|
DWord PngHeader::getWidth() const
|
||||||
|
{
|
||||||
|
return mWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWord PngHeader::getHeight() const
|
||||||
|
{
|
||||||
|
return mHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte PngHeader::getBitDepth() const
|
||||||
|
{
|
||||||
|
return mBitDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PngInfo& PngHeader::getPngInfo() const
|
||||||
|
{
|
||||||
|
return mPngInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWord PngHeader::getLength() const
|
||||||
{
|
{
|
||||||
return 13;
|
return 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char PngHeader::getHighBitCheck() const
|
Byte PngHeader::getHighBitCheck() const
|
||||||
{
|
{
|
||||||
return 0x89;
|
return 0x89;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> PngHeader::getSignature() const
|
void PngHeader::getSignature(VecBytes& sig) const
|
||||||
{
|
{
|
||||||
return {13, 10, 26, 10};
|
sig = {13, 10, 26, 10};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PngHeader::getFileName() const
|
std::string PngHeader::getFileName() const
|
||||||
|
@ -42,7 +62,7 @@ const std::string& PngHeader::getChunkName() const
|
||||||
return mName;
|
return mName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<unsigned char>& PngHeader::getData() const
|
const VecBytes& PngHeader::getData() const
|
||||||
{
|
{
|
||||||
return mData;
|
return mData;
|
||||||
}
|
}
|
||||||
|
@ -50,9 +70,9 @@ const std::vector<unsigned char>& PngHeader::getData() const
|
||||||
void PngHeader::updateData()
|
void PngHeader::updateData()
|
||||||
{
|
{
|
||||||
mData.clear();
|
mData.clear();
|
||||||
unsigned num_bytes = sizeof(uint32_t);
|
const auto num_bytes = sizeof(DWord);
|
||||||
|
|
||||||
for(unsigned idx=0; idx<num_bytes;idx++)
|
for(std::size_t idx=0; idx<num_bytes;idx++)
|
||||||
{
|
{
|
||||||
mData.push_back(ByteUtils::getByteN(mWidth, idx));
|
mData.push_back(ByteUtils::getByteN(mWidth, idx));
|
||||||
}
|
}
|
||||||
|
@ -62,13 +82,13 @@ void PngHeader::updateData()
|
||||||
mData.push_back(ByteUtils::getByteN(mHeight, idx));
|
mData.push_back(ByteUtils::getByteN(mHeight, idx));
|
||||||
}
|
}
|
||||||
mData.push_back(mBitDepth);
|
mData.push_back(mBitDepth);
|
||||||
mData.push_back(static_cast<unsigned char>(mPngInfo.mColorType));
|
mData.push_back(static_cast<Byte>(mPngInfo.mColorType));
|
||||||
mData.push_back(static_cast<unsigned char>(mPngInfo.mCompressionMethod));
|
mData.push_back(static_cast<Byte>(mPngInfo.mCompressionMethod));
|
||||||
mData.push_back(static_cast<unsigned char>(mPngInfo.mFilterMethod));
|
mData.push_back(static_cast<Byte>(mPngInfo.mFilterMethod));
|
||||||
mData.push_back(static_cast<unsigned char>(mPngInfo.mInterlaceMethod));
|
mData.push_back(static_cast<Byte>(mPngInfo.mInterlaceMethod));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t PngHeader::getCrc()
|
DWord PngHeader::getCrc()
|
||||||
{
|
{
|
||||||
CyclicRedundancyChecker crc_check;
|
CyclicRedundancyChecker crc_check;
|
||||||
std::vector<unsigned char> char_data = StringUtils::toBytes(mName);
|
std::vector<unsigned char> char_data = StringUtils::toBytes(mName);
|
||||||
|
|
|
@ -8,35 +8,23 @@
|
||||||
class PngHeader
|
class PngHeader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
uint32_t getLength() const;
|
DWord getLength() const;
|
||||||
|
|
||||||
uint32_t getCrc();
|
DWord getCrc();
|
||||||
|
|
||||||
const std::vector<unsigned char>& getData() const;
|
const VecBytes& getData() const;
|
||||||
|
|
||||||
uint32_t getWidth() const
|
DWord getWidth() const;
|
||||||
{
|
|
||||||
return mWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getHeight() const
|
DWord getHeight() const;
|
||||||
{
|
|
||||||
return mHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char getBitDepth() const
|
Byte getBitDepth() const;
|
||||||
{
|
|
||||||
return mBitDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PngInfo& getPngInfo() const
|
const PngInfo& getPngInfo() const;
|
||||||
{
|
|
||||||
return mPngInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char getHighBitCheck() const;
|
Byte getHighBitCheck() const;
|
||||||
|
|
||||||
std::vector<unsigned char> getSignature() const;
|
void getSignature(VecBytes& sig) const;
|
||||||
|
|
||||||
std::string getFileName() const;
|
std::string getFileName() const;
|
||||||
|
|
||||||
|
@ -44,20 +32,20 @@ public:
|
||||||
|
|
||||||
void setPngInfo(const PngInfo& info);
|
void setPngInfo(const PngInfo& info);
|
||||||
|
|
||||||
void setImageData(uint32_t width, uint32_t height, unsigned char bitDepth);
|
void setImageData(DWord width, DWord height, Byte bitDepth);
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
void updateData();
|
void updateData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t mWidth{0};
|
DWord mWidth{0};
|
||||||
uint32_t mHeight{0};
|
DWord mHeight{0};
|
||||||
unsigned char mBitDepth{0};
|
Byte mBitDepth{0};
|
||||||
PngInfo mPngInfo;
|
PngInfo mPngInfo;
|
||||||
std::string mName{"IHDR"};
|
std::string mName{"IHDR"};
|
||||||
|
|
||||||
uint32_t mCachedCrc{0};
|
DWord mCachedCrc{0};
|
||||||
|
|
||||||
std::vector<unsigned char> mData;
|
VecBytes mData;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,23 +19,9 @@ std::string PngInfo::toString(ColorType colorType) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PngInfo::getNumChannels() const
|
ColorType PngInfo::ColorType() const
|
||||||
{
|
{
|
||||||
switch(mColorType)
|
return mColorType;
|
||||||
{
|
|
||||||
case ColorType::GREYSCALE:
|
|
||||||
return 1;
|
|
||||||
case ColorType::RGB:
|
|
||||||
return 3;
|
|
||||||
case ColorType::PALETTE:
|
|
||||||
return 1;
|
|
||||||
case ColorType::GREYSCALE_ALPHA:
|
|
||||||
return 2;
|
|
||||||
case ColorType::RGB_ALPHA:
|
|
||||||
return 4;
|
|
||||||
default:
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PngInfo::toString(CompressionMethod method) const
|
std::string PngInfo::toString(CompressionMethod method) const
|
||||||
|
@ -73,7 +59,7 @@ std::string PngInfo::toString(InterlaceMethod method) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PngInfo::bitDepthIsValid(ColorType colorType, unsigned char bitDepth) const
|
bool PngInfo::bitDepthIsValid(ColorType colorType, Byte bitDepth) const
|
||||||
{
|
{
|
||||||
switch(colorType)
|
switch(colorType)
|
||||||
{
|
{
|
||||||
|
@ -92,12 +78,12 @@ bool PngInfo::bitDepthIsValid(ColorType colorType, unsigned char bitDepth) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PngInfo::compressionMethodIsValid(unsigned char method)
|
bool PngInfo::compressionMethodIsValid(Byte method)
|
||||||
{
|
{
|
||||||
return method == 0;
|
return method == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PngInfo::filterMethodIsValid(unsigned char method)
|
bool PngInfo::filterMethodIsValid(Byte method)
|
||||||
{
|
{
|
||||||
return method == 0;
|
return method == 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ByteTypes.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
class PngInfo
|
class PngInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class ColorType : unsigned char
|
enum class ColorType : Byte
|
||||||
{
|
{
|
||||||
GREYSCALE = 0,
|
GREYSCALE = 0,
|
||||||
RGB = 2,
|
RGB = 2,
|
||||||
|
@ -15,23 +17,23 @@ public:
|
||||||
RGB_ALPHA = 6
|
RGB_ALPHA = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CompressionMethod : unsigned char
|
enum class CompressionMethod : Byte
|
||||||
{
|
{
|
||||||
DEFLATE = 0
|
DEFLATE = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class FilterMethod : unsigned char
|
enum class FilterMethod : Byte
|
||||||
{
|
{
|
||||||
ADAPTIVE = 0
|
ADAPTIVE = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class InterlaceMethod : unsigned char
|
enum class InterlaceMethod : Byte
|
||||||
{
|
{
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
ADAM7 = 1
|
ADAM7 = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned getNumChannels() const;
|
ColorType getColorType() const;
|
||||||
|
|
||||||
std::string toString(ColorType colorType) const;
|
std::string toString(ColorType colorType) const;
|
||||||
|
|
||||||
|
@ -41,11 +43,11 @@ public:
|
||||||
|
|
||||||
std::string toString(InterlaceMethod method) const;
|
std::string toString(InterlaceMethod method) const;
|
||||||
|
|
||||||
bool bitDepthIsValid(ColorType colorType, unsigned char bitDepth) const;
|
bool bitDepthIsValid(ColorType colorType, Byte bitDepth) const;
|
||||||
|
|
||||||
bool compressionMethodIsValid(unsigned char method);
|
bool compressionMethodIsValid(Byte method);
|
||||||
|
|
||||||
bool filterMethodIsValid(unsigned char method);
|
bool filterMethodIsValid(Byte method);
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,15 @@ std::unique_ptr<PngWriter> PngWriter::Create()
|
||||||
return std::make_unique<PngWriter>();
|
return std::make_unique<PngWriter>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PngWriter::setCompressionMethod(Deflate::CompressionMethod method)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
(void)method;
|
||||||
|
#else
|
||||||
|
dynamic_cast<BasicPngWriter*>(mWriterImpl.get())->setCompressionMethod(method);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void PngWriter::write(const Path& path, Image* image)
|
void PngWriter::write(const Path& path, Image* image)
|
||||||
{
|
{
|
||||||
mWriterImpl->write(path, image);
|
mWriterImpl->write(path, image);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
#include "IImageWriter.h"
|
#include "IImageWriter.h"
|
||||||
|
#include "DeflateElements.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -14,6 +15,8 @@ public:
|
||||||
|
|
||||||
static std::unique_ptr<PngWriter> Create();
|
static std::unique_ptr<PngWriter> Create();
|
||||||
|
|
||||||
|
void setCompressionMethod(Deflate::CompressionMethod method);
|
||||||
|
|
||||||
void write(const Path& path, Image* image) override;
|
void write(const Path& path, Image* image) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
void WaylandInterface::registryHandleGlobalEvent(void *data, struct wl_registry *registry,
|
void WaylandInterface::registryHandleGlobalEvent(void *data, struct wl_registry *registry,
|
||||||
uint32_t name, const char *interface, uint32_t version)
|
uint32_t name, const char *interface, uint32_t version)
|
||||||
|
@ -41,6 +42,7 @@ void WaylandInterface::registryHandleGlobalEvent(void *data, struct wl_registry
|
||||||
|
|
||||||
void WaylandInterface::registryHandleGlobalRemoveEvent(void *data, struct wl_registry *registry, uint32_t name)
|
void WaylandInterface::registryHandleGlobalRemoveEvent(void *data, struct wl_registry *registry, uint32_t name)
|
||||||
{
|
{
|
||||||
|
std::cout << "remove handler called " << std::endl;
|
||||||
(void)data;
|
(void)data;
|
||||||
(void)registry;
|
(void)registry;
|
||||||
(void)name;
|
(void)name;
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "DrawingContext.h"
|
#include "DrawingContext.h"
|
||||||
#include "FontsManager.h"
|
#include "FontsManager.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
void WaylandSurface::add(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr<WaylandBuffer> buffer, FontsManager* fontsManager, WaylandEglInterface* eglInterface)
|
void WaylandSurface::add(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr<WaylandBuffer> buffer, FontsManager* fontsManager, WaylandEglInterface* eglInterface)
|
||||||
{
|
{
|
||||||
auto wayland_window = std::make_unique<WaylandSurface>(window, compositor, xdg_wm_base, buffer, eglInterface);
|
auto wayland_window = std::make_unique<WaylandSurface>(window, compositor, xdg_wm_base, buffer, eglInterface);
|
||||||
|
@ -78,7 +80,7 @@ void WaylandSurface::initialize()
|
||||||
void WaylandSurface::onConfigure(xdg_surface *xdg_surface, uint32_t serial)
|
void WaylandSurface::onConfigure(xdg_surface *xdg_surface, uint32_t serial)
|
||||||
{
|
{
|
||||||
xdg_surface_ack_configure(xdg_surface, serial);
|
xdg_surface_ack_configure(xdg_surface, serial);
|
||||||
beforePaint(nullptr);
|
mWindow->doPaint(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaylandSurface::beforePaint(mt::Screen* screen)
|
void WaylandSurface::beforePaint(mt::Screen* screen)
|
||||||
|
@ -124,21 +126,30 @@ void WaylandSurface::beforePaintSoftware()
|
||||||
const auto height = mWindow->getHeight();
|
const auto height = mWindow->getHeight();
|
||||||
const int stride = width * mWorkingBitDepth;
|
const int stride = width * mWorkingBitDepth;
|
||||||
|
|
||||||
|
std::cout << "before paint" << std::endl;
|
||||||
|
|
||||||
const int shm_pool_size = getImageBufferSize();
|
const int shm_pool_size = getImageBufferSize();
|
||||||
|
|
||||||
mBuffer->initializeSharedBuffer(shm_pool_size);
|
mBuffer->initializeSharedBuffer(shm_pool_size);
|
||||||
mBuffer->setUpPool(shm_pool_size, width, height, stride);
|
mBuffer->setUpPool(shm_pool_size, width, height, stride);
|
||||||
|
|
||||||
|
//int offset{0};
|
||||||
|
|
||||||
|
mWindow->getImage()->toBuffer(mBuffer->getPoolData(), width*height*stride, Image::Format::ARGB);
|
||||||
|
|
||||||
//ImagePrimitives::drawCheckerboard(mBuffer->getPoolData(), width, height, offset);
|
//ImagePrimitives::drawCheckerboard(mBuffer->getPoolData(), width, height, offset);
|
||||||
|
std::cout << "checkerboard drawn" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaylandSurface::afterPaintSoftware()
|
void WaylandSurface::afterPaintSoftware()
|
||||||
{
|
{
|
||||||
|
std::cout << "after paint" << std::endl;
|
||||||
|
|
||||||
const int shm_pool_size = getImageBufferSize();
|
const int shm_pool_size = getImageBufferSize();
|
||||||
mBuffer->tearDownPool(shm_pool_size);
|
mBuffer->tearDownPool(shm_pool_size);
|
||||||
|
|
||||||
wl_surface_attach(mSurface, mBuffer->getWorkingBuffer(), 0, 0);
|
wl_surface_attach(mSurface, mBuffer->getWorkingBuffer(), 0, 0);
|
||||||
//wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX);
|
wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX);
|
||||||
wl_surface_commit(mSurface);
|
wl_surface_commit(mSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ private:
|
||||||
|
|
||||||
unsigned getImageBufferSize() const;
|
unsigned getImageBufferSize() const;
|
||||||
|
|
||||||
mt::Window* mWindow{nullptr};
|
//mt::Window* mWindow{nullptr};
|
||||||
|
|
||||||
wl_compositor* mCompositor{nullptr};
|
wl_compositor* mCompositor{nullptr};
|
||||||
xdg_wm_base* mXdgWmBase{nullptr};
|
xdg_wm_base* mXdgWmBase{nullptr};
|
||||||
|
|
|
@ -4,6 +4,7 @@ set(UNIT_TEST_TARGETS)
|
||||||
set(INTEGRATION_TEST_TARGETS)
|
set(INTEGRATION_TEST_TARGETS)
|
||||||
|
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
|
#add_subdirectory(console)
|
||||||
add_subdirectory(database)
|
add_subdirectory(database)
|
||||||
add_subdirectory(fonts)
|
add_subdirectory(fonts)
|
||||||
add_subdirectory(geometry)
|
add_subdirectory(geometry)
|
||||||
|
@ -18,6 +19,7 @@ set(TEST_MODULES
|
||||||
audio
|
audio
|
||||||
compiler
|
compiler
|
||||||
compression
|
compression
|
||||||
|
console
|
||||||
image
|
image
|
||||||
ipc
|
ipc
|
||||||
mesh
|
mesh
|
||||||
|
|
23
test/bootstrap_tests.sh
Executable file
23
test/bootstrap_tests.sh
Executable 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
|
9
test/console/CMakeLists.txt
Normal file
9
test/console/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
include(TestTargets)
|
||||||
|
|
||||||
|
unit_tests(
|
||||||
|
MODULE_NAME console
|
||||||
|
FILES
|
||||||
|
TestConsoleApp.cpp
|
||||||
|
DEPENDENCIES
|
||||||
|
console
|
||||||
|
)
|
93
test/console/TestConsoleApp.cpp
Normal file
93
test/console/TestConsoleApp.cpp
Normal 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);
|
||||||
|
}
|
|
@ -1,8 +1,43 @@
|
||||||
#include "StringUtils.h"
|
#include "String.h"
|
||||||
|
|
||||||
#include "TestFramework.h"
|
#include "TestFramework.h"
|
||||||
#include "TestUtils.h"
|
//#include "TestUtils.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
TEST_CASE(TestBasicStringOps, "core")
|
||||||
|
{
|
||||||
|
String str;
|
||||||
|
str += 'a';
|
||||||
|
str += 'b';
|
||||||
|
str += 'c';
|
||||||
|
str += 'd';
|
||||||
|
REQUIRE(str == "abcd");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(TestStringReverse, "core")
|
||||||
|
{
|
||||||
|
String str0;
|
||||||
|
str0.reverse();
|
||||||
|
REQUIRE(str0.empty());
|
||||||
|
|
||||||
|
String str1("a");
|
||||||
|
str1.reverse();
|
||||||
|
REQUIRE(str1 == "a");
|
||||||
|
|
||||||
|
String str2("ab");
|
||||||
|
str2.reverse();
|
||||||
|
REQUIRE(str2 == "ba");
|
||||||
|
|
||||||
|
String str3("abc");
|
||||||
|
str3.reverse();
|
||||||
|
REQUIRE(str3 == "cba");
|
||||||
|
|
||||||
|
String str4("abcd");
|
||||||
|
str4.reverse();
|
||||||
|
REQUIRE(str4 == "dcba");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
TEST_CASE(TestStringUtils_StripSurroundingWhitepsace, "core")
|
TEST_CASE(TestStringUtils_StripSurroundingWhitepsace, "core")
|
||||||
{
|
{
|
||||||
std::string input = " super() ";
|
std::string input = " super() ";
|
||||||
|
@ -28,3 +63,5 @@ TEST_CASE(TestStringUtils_startsWith, "core")
|
||||||
starts_with = StringUtils::startsWith(input, "```", ignore_whitespace);
|
starts_with = StringUtils::startsWith(input, "```", ignore_whitespace);
|
||||||
REQUIRE(starts_with);
|
REQUIRE(starts_with);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
18
test/core/TestVector.cpp
Normal file
18
test/core/TestVector.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@
|
||||||
#include "TestUtils.h"
|
#include "TestUtils.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
TEST_CASE(TestCompressedPng, "image")
|
TEST_CASE(TestUncompressedPng, "image")
|
||||||
{
|
{
|
||||||
unsigned width = 20;
|
unsigned width = 20;
|
||||||
unsigned height = 20;
|
unsigned height = 20;
|
||||||
|
@ -30,13 +30,14 @@ TEST_CASE(TestCompressedPng, "image")
|
||||||
image->getGridT<unsigned char>()->setData(data);
|
image->getGridT<unsigned char>()->setData(data);
|
||||||
|
|
||||||
PngWriter writer;
|
PngWriter writer;
|
||||||
//writer.setCompressionMethod(Deflate::CompressionMethod::NONE);
|
writer.setCompressionMethod(Deflate::CompressionMethod::NONE);
|
||||||
writer.write(TestUtils::getTestOutputDir() / "test_compressed.png", image.get());
|
writer.write(TestUtils::getTestOutputDir(__FILE__) / "test_uncompressed.png", image.get());
|
||||||
|
|
||||||
return;
|
File test_file(TestUtils::getTestOutputDir(__FILE__) / "test_uncompressed.png");
|
||||||
File test_file(TestUtils::getTestOutputDir() / "test_compressed.png");
|
|
||||||
test_file.open(File::AccessMode::Read);
|
test_file.open(File::AccessMode::Read);
|
||||||
|
|
||||||
|
std::cout << test_file.dumpBinary();
|
||||||
|
return;
|
||||||
while(auto byte = test_file.readNextByte())
|
while(auto byte = test_file.readNextByte())
|
||||||
{
|
{
|
||||||
//std::cout << static_cast<unsigned>(*byte) << std::endl;
|
//std::cout << static_cast<unsigned>(*byte) << std::endl;
|
||||||
|
@ -63,13 +64,8 @@ TEST_CASE(TestFixedPng, "image")
|
||||||
image->getGridT<unsigned char>()->setData(data);
|
image->getGridT<unsigned char>()->setData(data);
|
||||||
|
|
||||||
PngWriter writer;
|
PngWriter writer;
|
||||||
//writer.setCompressionMethod(Deflate::CompressionMethod::FIXED_HUFFMAN);
|
writer.setCompressionMethod(Deflate::CompressionMethod::FIXED_HUFFMAN);
|
||||||
writer.write(TestUtils::getTestOutputDir() / "test_fixed.png", image.get());
|
writer.write(TestUtils::getTestOutputDir(__FILE__) / "test_fixed.png", image.get());
|
||||||
|
|
||||||
//return;
|
|
||||||
File test_file(TestUtils::getTestOutputDir() / "test_fixed.png");
|
|
||||||
//std::cout << test_file.dumpBinary();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(TestDynamicCompressedPng, "image")
|
TEST_CASE(TestDynamicCompressedPng, "image")
|
||||||
|
@ -93,9 +89,9 @@ TEST_CASE(TestDynamicCompressedPng, "image")
|
||||||
|
|
||||||
PngWriter writer;
|
PngWriter writer;
|
||||||
//writer.setPath(TestUtils::getTestOutputDir() / "test_dynamic.png");
|
//writer.setPath(TestUtils::getTestOutputDir() / "test_dynamic.png");
|
||||||
writer.write(TestUtils::getTestOutputDir() / "test_dynamic.png", image.get());
|
writer.write(TestUtils::getTestOutputDir(__FILE__) / "test_dynamic.png", image.get());
|
||||||
|
|
||||||
//return;
|
//return;
|
||||||
File test_file(TestUtils::getTestOutputDir() / "test_dynamic.png");
|
File test_file(TestUtils::getTestOutputDir(__FILE__) / "test_dynamic.png");
|
||||||
//std::cout << test_file.dumpBinary();
|
//std::cout << test_file.dumpBinary();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "TestFramework.h"
|
#include "TestFramework.h"
|
||||||
|
|
||||||
#include "CommandLineArgs.h"
|
#include "CommandLineArgs.h"
|
||||||
|
#include "ConsoleLogger.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -13,10 +14,12 @@ int main(int argc, char *argv[])
|
||||||
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto args = CommandLineArgs::Create();
|
CommandLineArgs args;
|
||||||
args->process(argc, argv);
|
args.process(argc, argv);
|
||||||
|
|
||||||
TestCaseRunner::getInstance().run(args->getUserArgs());
|
ConsoleLogger::logLine("Starting test run.");
|
||||||
|
TestCaseRunner::getInstance().run(args.getUserArgs());
|
||||||
|
ConsoleLogger::logLine("Finished test run.");
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include "String.h"
|
||||||
#include <string>
|
#include "Pointer.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
class TestCase
|
class TestCase
|
||||||
|
@ -9,7 +9,7 @@ class TestCase
|
||||||
public:
|
public:
|
||||||
using TestCaseFunction = std::function<void()>;
|
using TestCaseFunction = std::function<void()>;
|
||||||
|
|
||||||
TestCase(const std::string& name, const std::string& tags, TestCaseFunction func)
|
TestCase(const String& name, const String& tags, TestCaseFunction func)
|
||||||
: mTestFunction(func),
|
: mTestFunction(func),
|
||||||
mName(name),
|
mName(name),
|
||||||
mTags(tags)
|
mTags(tags)
|
||||||
|
@ -19,12 +19,12 @@ public:
|
||||||
|
|
||||||
virtual ~TestCase() = default;
|
virtual ~TestCase() = default;
|
||||||
|
|
||||||
const std::string& getName() const
|
const String& getName() const
|
||||||
{
|
{
|
||||||
return mName;
|
return mName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& getTags() const
|
const String& getTags() const
|
||||||
{
|
{
|
||||||
return mTags;
|
return mTags;
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,8 @@ public:
|
||||||
TestCaseFunction mTestFunction{nullptr};
|
TestCaseFunction mTestFunction{nullptr};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mName;
|
String mName;
|
||||||
std::string mTags;
|
String mTags;
|
||||||
|
|
||||||
};
|
};
|
||||||
using TestCasePtr = std::unique_ptr<TestCase>;
|
using TestCasePtr = Ptr<TestCase>;
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
#include "TestCaseRunner.h"
|
#include "TestCaseRunner.h"
|
||||||
|
|
||||||
#include "FileLogger.h"
|
#include "FileLogger.h"
|
||||||
#include "TestUiApplication.h"
|
#include "ConsoleLogger.h"
|
||||||
|
//#include "TestUiApplication.h"
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
bool TestCaseRunner::sLastTestFailed = false;
|
bool TestCaseRunner::sLastTestFailed = false;
|
||||||
std::string TestCaseRunner::sFailureLine = {};
|
String TestCaseRunner::sFailureLine = {};
|
||||||
|
|
||||||
TestCaseRunner::TestCaseRunner()
|
TestCaseRunner::TestCaseRunner()
|
||||||
{
|
{
|
||||||
|
@ -19,6 +17,7 @@ TestCaseRunner::~TestCaseRunner()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
TestUiApplication* TestCaseRunner::getTestApplication()
|
TestUiApplication* TestCaseRunner::getTestApplication()
|
||||||
{
|
{
|
||||||
return mTestApplication;
|
return mTestApplication;
|
||||||
|
@ -28,6 +27,7 @@ void TestCaseRunner::setTestApplication(TestUiApplication* app)
|
||||||
{
|
{
|
||||||
mTestApplication = app;
|
mTestApplication = app;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
TestCaseRunner& TestCaseRunner::getInstance()
|
TestCaseRunner& TestCaseRunner::getInstance()
|
||||||
{
|
{
|
||||||
|
@ -35,26 +35,26 @@ TestCaseRunner& TestCaseRunner::getInstance()
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCaseRunner::addTestCase(const std::string& label, const std::string& tag, TestCase::TestCaseFunction func)
|
void TestCaseRunner::addTestCase(const String& label, const String& tag, TestCase::TestCaseFunction func)
|
||||||
{
|
{
|
||||||
auto test_case = new TestCase(label, tag, func);
|
auto test_case = new TestCase(label, tag, func);
|
||||||
mCases.push_back(test_case);
|
mCases.push_back(test_case);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCaseRunner::markTestFailure(const std::string& line)
|
void TestCaseRunner::markTestFailure(const String& line)
|
||||||
{
|
{
|
||||||
sLastTestFailed = true;
|
sLastTestFailed = true;
|
||||||
sFailureLine = line;
|
sFailureLine = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestCaseRunner::run(const std::vector<std::string>& args)
|
bool TestCaseRunner::run(const Vector<String>& args)
|
||||||
{
|
{
|
||||||
std::string test_to_run;
|
String test_to_run;
|
||||||
if (args.size() > 0 )
|
if (args.size() > 0 )
|
||||||
{
|
{
|
||||||
test_to_run = args[0];
|
test_to_run = args[0];
|
||||||
}
|
}
|
||||||
FileLogger::GetInstance().disable();
|
//FileLogger::GetInstance().disable();
|
||||||
for (auto test_case : mCases)
|
for (auto test_case : mCases)
|
||||||
{
|
{
|
||||||
if (!test_to_run.empty())
|
if (!test_to_run.empty())
|
||||||
|
@ -66,41 +66,22 @@ bool TestCaseRunner::run(const std::vector<std::string>& args)
|
||||||
}
|
}
|
||||||
|
|
||||||
sLastTestFailed = false;
|
sLastTestFailed = false;
|
||||||
std::cout << "TestFramework: Running Test - " << test_case->getName() << std::endl;
|
ConsoleLogger::logLine("TestFramework: Running Test - %s", test_case->getName().raw());
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
test_case->run();
|
test_case->run();
|
||||||
}
|
|
||||||
catch (const std::runtime_error& re)
|
|
||||||
{
|
|
||||||
std::cout << "Failed with runtime error: " << re.what() << std::endl;
|
|
||||||
mFailingTests.push_back(test_case->getName());
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
std::cout << "Failed with exception: " << e.what() << std::endl;
|
|
||||||
mFailingTests.push_back(test_case->getName());
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
std::cout << "Failed with unknown exception" << std::endl;
|
|
||||||
mFailingTests.push_back(test_case->getName());
|
|
||||||
};
|
|
||||||
|
|
||||||
if (sLastTestFailed)
|
if (sLastTestFailed)
|
||||||
{
|
{
|
||||||
std::cout << "Failed at line: " << sFailureLine << std::endl;
|
ConsoleLogger::logLine("Failed at line %s", sFailureLine.raw());
|
||||||
mFailingTests.push_back(test_case->getName());
|
mFailingTests.push_back(test_case->getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFailingTests.size() > 0)
|
if (mFailingTests.size() > 0)
|
||||||
{
|
{
|
||||||
std::cout << mFailingTests.size() << " failing tests: " << std::endl;
|
ConsoleLogger::logLine("%d failing tests", mFailingTests.size());
|
||||||
for(const auto& name : mFailingTests)
|
for(const auto& name : mFailingTests)
|
||||||
{
|
{
|
||||||
std::cout << name << std::endl;
|
ConsoleLogger::logLine(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#include "TestCase.h"
|
#include "TestCase.h"
|
||||||
|
|
||||||
#include <vector>
|
#include "Vector.h"
|
||||||
#include <string>
|
#include "String.h"
|
||||||
|
|
||||||
class TestUiApplication;
|
class TestUiApplication;
|
||||||
|
|
||||||
|
@ -16,20 +16,20 @@ public:
|
||||||
|
|
||||||
~TestCaseRunner();
|
~TestCaseRunner();
|
||||||
|
|
||||||
TestUiApplication* getTestApplication();
|
//TestUiApplication* getTestApplication();
|
||||||
|
|
||||||
void addTestCase(const std::string& label, const std::string& tag, TestCase::TestCaseFunction func);
|
void addTestCase(const String& label, const String& tag, TestCase::TestCaseFunction func);
|
||||||
|
|
||||||
void markTestFailure(const std::string& line);
|
void markTestFailure(const String& line);
|
||||||
|
|
||||||
bool run(const std::vector<std::string>& args);
|
bool run(const Vector<String>& args);
|
||||||
|
|
||||||
void setTestApplication(TestUiApplication* app);
|
//void setTestApplication(TestUiApplication* app);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
TestUiApplication* mTestApplication{ nullptr };
|
//TestUiApplication* mTestApplication{ nullptr };
|
||||||
std::vector<std::string> mFailingTests;
|
Vector<String> mFailingTests;
|
||||||
static bool sLastTestFailed;
|
static bool sLastTestFailed;
|
||||||
static std::string sFailureLine;
|
static String sFailureLine;
|
||||||
std::vector<TestCase*> mCases;
|
Vector<TestCase*> mCases;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
struct Holder
|
struct Holder
|
||||||
{
|
{
|
||||||
Holder(const std::string& name, const std::string& tags, std::function<void()> func)
|
Holder(const String& name, const String& tags, std::function<void()> func)
|
||||||
{
|
{
|
||||||
TestCaseRunner::getInstance().addTestCase(name, tags, func);
|
TestCaseRunner::getInstance().addTestCase(name, tags, func);
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ struct Holder
|
||||||
#define REQUIRE(predicate) \
|
#define REQUIRE(predicate) \
|
||||||
if(!bool(predicate)) \
|
if(!bool(predicate)) \
|
||||||
{ \
|
{ \
|
||||||
TestCaseRunner::getInstance().markTestFailure(std::to_string(__LINE__) + " with check: '" + std::string(#predicate) + "'"); \
|
const auto msg = String::to_string(__LINE__) + String(" with check: '") + String(#predicate) + String("'"); \
|
||||||
return; \
|
TestCaseRunner::getInstance().markTestFailure(msg); \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "TestDataLocations.h"
|
//#include "TestDataLocations.h"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
|
|
@ -16,5 +16,5 @@ TEST_CASE(TestWaylandWindow, "web")
|
||||||
//app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND);
|
//app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND);
|
||||||
app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND_RASTER);
|
app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND_RASTER);
|
||||||
|
|
||||||
app->run();
|
//app->run();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue