Skip to content

Pennywise007/ext

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ext library

Header only C++17 extensions library

Dependency injection

Usage simple with .Net Microsoft.Extensions.DependencyInjection

Example
#include <ext/core/dependency_injection.h>


struct InterfaceExample
{
    virtual ~InterfaceExample() = default;
};

struct InterfaceImplementationExample : InterfaceExample
{};

struct CreatedObjectExample : ext::ServiceProviderHolder
{
    explicit CreatedObjectExample(std::shared_ptr<InterfaceExample> interfaceShared, std::lazy_interface<InterfaceExample> interfaceLazy, ext::ServiceProvider::Ptr&& serviceProvider)
        : ServiceProviderHolder(std::move(serviceProvider))
        , m_interfaceShared(std::move(interfaceShared))
        , m_interfaceLazyOne(std::move(interfaceLazy))
        , m_interfaceLazyTwo(ServiceProviderHolder::m_serviceProvider)
    {}

    std::shared_ptr<IRandomInterface> GetRandomInterface() const
    {
        return ServiceProviderHolder::GetInterface<IRandomInterface>();
    }

    std::shared_ptr<IRandomInterface> GetRandomInterfaceOption2() const
    {
        return ext::GetInterface<IRandomInterface>(ServiceProviderHolder::m_serviceProvider);
    }

    std::shared_ptr<InterfaceExample> m_interfaceShared;
    ext::lazy_interface<InterfaceExample> m_interfaceLazyOne;
    ext::lazy_interface<InterfaceExample> m_interfaceLazyTwo;
};

ext::ServiceCollection& serviceCollection = ext::get_singleton<ext::ServiceCollection>();
serviceCollection.RegisterScoped<InterfaceImplementationExample, InterfaceExample>();

const std::shared_ptr<CreatedObjectExample> object = ext::CreateObject<CreatedObjectExample>(serviceCollection.BuildServiceProvider());

Serialization

Serialization objects to/from text, xml

Example
#include <ext/serialization/iserializable.h>

using namespace ext::serializable;
using namespace ext::serializer;

struct Settings
{
    struct User
    {
        REGISTER_SERIALIZABLE_OBJECT();

        DECLARE_SERIALIZABLE_FIELD(std::int64_t, id);
        DECLARE_SERIALIZABLE_FIELD(std::string, firstName);
        DECLARE_SERIALIZABLE_FIELD(std::string, userName);
    };
    
    REGISTER_SERIALIZABLE_OBJECT_N("My settings");
    DECLARE_SERIALIZABLE_FIELD(std::wstring, token);
    DECLARE_SERIALIZABLE_FIELD(std::wstring, password);
    DECLARE_SERIALIZABLE_FIELD(std::list<User>, registeredUsers);

	Settings(){
        std::wstring text;
		if (!DeserializeObject(Factory::TextDeserializer(text), *this))
			...
	}
	~Settings() {
        std::wstring text;
		if (!SerializeObject(Factory::TextSerializer(text), *this))
			...
	}
};

Event dispatcher

Allow to register events and notify subscribers

Example
#include <ext/core/dispatcher.h>

// Example of event interface
struct IEvent : ext::events::IBaseEvent
{
	virtual void Event(int val) = 0;
};

// Example of sending an event:
ext::send_event(&IEvent::Event, 10);

// Example of recipient:
struct Recipient : ext::events::ScopeSubscription<IEvent>
{
	void Event(int val) override { std::cout << "Event"; }
}

Threading

Interruptible thread(boost/thread analog)
#include <ext/thread/thread.h>

ext::thread myThread(thread_function, []()
{
	while (!ext::this_thread::interruption_requested())
	{
		try
		{
			...
		}
		catch (const ext::thread::thread_interrupted&)
		{
			break;
		}
	}
});

myThread.interrupt();
EXPECT_TRUE(myThread.interrupted());
Thread pool
#include <ext/thread/thread_pool.h>

std::set<ext::task::TaskId, ext::task::TaskIdComparer> taskList;
ext::thread_pool threadPool([&taskList, &listMutex](const ext::task::TaskId& taskId)
{
	taskList.erase(taskId);
});

const auto maxThreads = std::thread::hardware_concurrency();
for (auto i = maxThreads; i != 0; --i)
{
	taskList.emplace(threadPool.add_task([]()
	{
		...
	}));
}
threadPool.wait_for_tasks();

And others:

ext::Channel<int> channel;

std::thread([&]()
    {
        for (auto val : channel) {
            ...
        }
    });
channel.add(1);
channel.add(10);
channel.close();
ext::stop_source source;
ext::thread myThread([stop_token = source.get_token()]()
{
    while (!stop_token.stop_requested())
    {
        ...
    }
});

source.request_stop();
myThread.join();

Tracer

Show traces with defferent levels and time stamps in cout/cerr/output/trace file
#include <ext/core/tracer.h>
ext::get_tracer().Enable();

Simple macroses: Default information trace EXT_TRACE() << "My trace";

Debug information only for Debug build EXT_TRACE_DBG() << EXT_TRACE_FUNCTION "called";

Error trace to cerr, mostly used in EXT_CHECK/EXT_EXPECT EXT_TRACE_ERR() << EXT_TRACE_FUNCTION "called";

Can be called for scope call function check. Trace start and end scope with the given text EXT_TRACE_SCOPE() << EXT_TRACE_FUNCTION << "Main function called with " << args;

Check code execution and handling errors

Allows to add simple checks inside executing code and manage ezxceptions
#include <ext/core/check.h>

EXT_CHECK - throws exception if expression is false

EXT_CHECK(bool_expression) << "Text";

if (!bool_expression)
	throw ::ext::check::CheckFailedException(EXT_SRC_LOCATION, #bool_expression "Text");

EXT_EXPECT - if expression is false:

  • Only on first failure: debug break if debugger presents, create dump otherwise
  • throws exception

EXT_EXPECT(bool_expression) << "Text";

if (!bool_expression)
{
	if (IsDebuggerPresent())                                            
		DebugBreak();                                                   
	else                                                                
		EXT_DUMP_CREATE();
	throw ::ext::check::CheckFailedException(EXT_SRC_LOCATION, #bool_expression "Text"));
}

EXT_ASSERT / EXT_REQUIRE - if expression is false in debug mode. Only on first failure: debug break if debugger presents, create dump otherwise

EXT_ASSERT(bool_expression) << "Text";

#ifdef _DEBUG
if (!bool_expression)
{
	if (IsDebuggerPresent())                                            
		DebugBreak();                                                   
	else                                                                
		EXT_DUMP_CREATE();
}
#endif

Managing exceptions

Allow to simplify managing exceptions and output error text
#include <ext/error/exception.h>

try
{ 
	EXT_EXPECT(is_ok()) << "Something wrong!";
}
catch (...)
{	
	try
	{
		std::throw_with_nested(ext::exception(EXT_SRC_LOCATION, "Job failed")); 
	}
	catch (...)
	{
		::MessageBox(NULL, ext::ManageExceptionText("Big bang"));
	}
}

Dumper and debugging

Allow to catch unhandled exceptions and generate dump file

Declare unhandled exceptions handler(called automatic on calling ext::dump::create_dump())

#include <ext/error/dump_writer.h>

void main()
{
	EXT_DUMP_DECLARE_HANDLER();
	...
}

If you need to catch error inside you code you add check:

EXT_DUMP_IF(is_something_wrong());

In this case if debugger presents - it will be stopped here, otherwise generate dump file and continue execution, @see DEBUG_BREAK_OR_CREATE_DUMP. Dump generation and debug break in case with EXT_DUMP_IF generates only once to avoid spam.

Compile time classes

Constexpr string

Allows to combine and check text in compile time.

#include <ext/constexpr/string.h>

constexpr ext::constexpr_string textFirst = "test";
constexpr ext::constexpr_string textSecond = "second";

constexpr auto TextCombination = textFirst + "_" + textSecond;
static_assert(TextCombination == "test_second");

In C++20 can be used to store text as a template argument:

    template <ext::constexpr_string name__>
    struct Object {
        constexpr std::string_view Name() const {
            return name__.str();
        }
        ...
    };

    Object<"object_name"> object;
    static_assert(object.Name() == std::string_view("object_name"));

Source

Constexpr map

Compile time extension for strings, allow to combine and check text in compile time.

#include <ext/constexpr/map.h>

constexpr ext::constexpr_map my_map = {{std::pair{11, 10}, {std::pair{22, 33}}}};
static_assert(my_map.size() == 2);

static_assert(10 == my_map.get_value(11));
static_assert(33 == my_map.get_value(22));

Source

Std extensions

Memory:

  • lazy_shared_ptr - allow to create a shared memory which will be created only on first call

Strings:

Filesystem:

Other

Build

CMake build and run tests
mkdir build
cd build
cmake .. -DEXT_BUILD_TESTS=ON
cmake --build . --parallel
# On windows
.\tests\Debug\ext_tests.exe
# On linux
./tests/ext_tests