diff --git a/README.md b/README.md index 7108fdd..9759a87 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ It is a general purpose C++ library that can help developers create various kind Please go to https://gitlab.com/ii887522/nitro to start contributing instead. ## Prerequisites -- Windows 10 - [Docker Desktop](https://www.docker.com/products/docker-desktop) using Windows containers - [Visual Studio Code](https://code.visualstudio.com/) - Docker @@ -33,23 +32,23 @@ Please go to https://gitlab.com/ii887522/nitro to start contributing instead. ## Update .NET Framework SDK version used by ms-build-tools to match your OS 1. Left click on the start button at the bottom left corner of your desktop. - + Start button

2. Left click on the settings button at the left side of the start menu. - + Settings

3. Left click on the system button at the top left corner of settings window. - + System

4. Left click on the about button at the bottom left corner of settings window. - + About

5. Take note of the version shown in the settings window. You will need it to search for appropriate tags later. - + Version

6. Go to https://hub.docker.com/_/microsoft-dotnet-framework-sdk/ and find Full Tag Listing section. @@ -81,3 +80,8 @@ install ```sh build ``` + +### Deploy project +```sh +deploy +``` diff --git a/deploy.cmd b/deploy.cmd new file mode 100644 index 0000000..0ba693f --- /dev/null +++ b/deploy.cmd @@ -0,0 +1,4 @@ +docker run --rm --name nitro_bundler -w C:\nitro -v %CD%:C:\nitro mcr.microsoft.com/windows/servercore:20H2 cmd /c mkdir libs && cd libs && mkdir nitro && cd nitro && mkdir include && cd include && xcopy ..\..\..\nitro\src\main\ .\ /s && cd .. && mkdir lib && cd lib && mkdir x86 && cd x86 && mkdir Debug && cd Debug && copy ..\..\..\..\..\nitro\Debug\nitro.lib .\ && cd .. && mkdir Release && cd Release && copy ..\..\..\..\..\nitro\Release\nitro.lib .\ && cd .. && cd .. && mkdir x64 && cd x64 && mkdir Debug && cd Debug && copy ..\..\..\..\..\nitro\x64\Debug\nitro.lib .\ && cd .. && mkdir Release && cd Release && copy ..\..\..\..\..\nitro\x64\Release\nitro.lib .\ && cd .. && cd .. && cd .. && cd .. && cd .. +docker run --rm --name nitro_zipper -w C:\nitro\libs -v %CD%\libs:C:\nitro\libs kiazhi/nanoserver.7-zip:1709-18.05 7z a nitro.zip nitro\ +docker run --rm --name nitro_publisher -v %CD%\libs:C:\nitro\libs stefanscherer/curl-windows:7.58.0 --header "PRIVATE-TOKEN: %1" --upload-file C:\nitro\libs\nitro.zip https://gitlab.com/api/v4/projects/23530641/packages/generic/nitro/1.0.0/nitro.zip +docker run --rm --name nitro_cleaner -w C:\nitro -v %CD%:C:\nitro mcr.microsoft.com/windows/servercore:20H2 cmd /c rmdir libs /s /q diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..44b9597 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,4 @@ +docker run --rm --name nitro_bundler -w C:/nitro -v $PWD:C:/nitro mcr.microsoft.com/windows/servercore:20H2 cmd /c mkdir libs && cd libs && mkdir nitro && cd nitro && mkdir include && cd include && xcopy ..\..\..\nitro\src\main\ .\ /s && cd .. && mkdir lib && cd lib && mkdir x86 && cd x86 && mkdir Debug && cd Debug && copy ..\..\..\..\..\nitro\Debug\nitro.lib .\ && cd .. && mkdir Release && cd Release && copy ..\..\..\..\..\nitro\Release\nitro.lib .\ && cd .. && cd .. && mkdir x64 && cd x64 && mkdir Debug && cd Debug && copy ..\..\..\..\..\nitro\x64\Debug\nitro.lib .\ && cd .. && mkdir Release && cd Release && copy ..\..\..\..\..\nitro\x64\Release\nitro.lib .\ && cd .. && cd .. && cd .. && cd .. && cd .. +docker run --rm --name nitro_zipper -w C:/nitro/libs -v $PWD/libs:C:/nitro/libs kiazhi/nanoserver.7-zip:1709-18.05 7z a nitro.zip nitro\ +docker run --rm --name nitro_publisher -v $PWD/libs:C:/nitro/libs stefanscherer/curl-windows:7.58.0 --header "PRIVATE-TOKEN: %1" --upload-file C:\nitro\libs\nitro.zip https://gitlab.com/api/v4/projects/23530641/packages/generic/nitro/1.0.0/nitro.zip +docker run --rm --name nitro_cleaner -w C:/nitro -v $PWD:C:/nitro mcr.microsoft.com/windows/servercore:20H2 cmd /c rmdir libs /s /q diff --git a/nitro/nitro.vcxproj b/nitro/nitro.vcxproj index e508d93..2bc712e 100644 --- a/nitro/nitro.vcxproj +++ b/nitro/nitro.vcxproj @@ -26,6 +26,34 @@ x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 16.0 Win32Proj @@ -134,7 +162,7 @@ Level4 true - TEST;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + TEST;LINEAR_ALLOCATOR;LONG_TERM_ALLOCATOR_SIZE=5304u;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpplatest stdc17 @@ -187,7 +215,7 @@ Level4 true - TEST;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + TEST;LINEAR_ALLOCATOR;LONG_TERM_ALLOCATOR_SIZE=8168u;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpplatest stdc17 @@ -220,9 +248,6 @@ true - - - diff --git a/nitro/nitro.vcxproj.filters b/nitro/nitro.vcxproj.filters index 79656db..6590d8f 100644 --- a/nitro/nitro.vcxproj.filters +++ b/nitro/nitro.vcxproj.filters @@ -19,10 +19,120 @@ {b6579c0e-bfe8-4b51-a187-60404b74ee71} + + {f0392f57-51f8-4dc9-97a3-b81564a6f838} + + + {a72974c4-fac4-4d9d-b801-d13def8aac60} + + + {179e3bd4-fe02-4d7f-b2c3-639b6eb8d1b2} + + + {8784fcff-f52c-416a-b6f4-8a214819be53} + + + {a853a5d0-5bcd-465b-82a6-3dffb5baa298} + + + {72b06555-60e9-4409-a99e-73b6d6a528d2} + + + {3d0bbcbf-74bb-4101-ac26-4038e54e4683} + + + {19558d27-8bc0-4ec7-9c03-6af01d816423} + + + {82739f87-9db2-42b4-b145-3e1617770a1d} + + + {3e1422de-17a3-4af0-b792-303b91900ac7} + + + {3bed952f-5fd6-4645-8fb4-13f0598a4dbe} + + + {89423a92-d04d-44fb-b078-e3c3909887d4} + + + {32fab255-14c2-421b-b489-35537f8e9d5e} + + + + + Header Files\Any + + + Header Files\Any + + + Header Files\Functions + + + Header Files\Functions + + + Header Files\Struct + + + Header Files\Struct + + + Header Files\Reactive + + + Header Files\Reactive + + + Test Header Files\Any + + + Test Header Files\Any + + + Test Header Files\Functions + + + Test Header Files\Functions + + + Test Header Files\Struct + + + Test Header Files\Reactive + + + Test Header Files\Reactive + - - Test Source Files + + Test Source Files\Functions + + + Test Source Files\Functions + + + Test Source Files\Functions + + + Test Source Files\Struct + + + Test Source Files\Reactive + + + Test Source Files\Reactive + + + Test Source Files\Any + + + Test Source Files\Any + + + Header Files\Allocator \ No newline at end of file diff --git a/nitro/src/main/Allocator/linear_allocator.h b/nitro/src/main/Allocator/linear_allocator.h new file mode 100644 index 0000000..fb973f3 --- /dev/null +++ b/nitro/src/main/Allocator/linear_allocator.h @@ -0,0 +1,103 @@ +#ifdef LINEAR_ALLOCATOR + +#ifndef II887522_NITRO_LINEAR_ALLOCATOR_H +#define II887522_NITRO_LINEAR_ALLOCATOR_H + +#include "../Functions/math_ext.h" +#include + +using ii887522::nitro::min; +using std::bad_alloc; + +#ifdef _DEBUG +#include + +using std::cout; +#endif + +namespace ii887522::nitro +{ + enum class Term : unsigned int + { + LONG, SHORT + }; + + static char longTermData[LONG_TERM_ALLOCATOR_SIZE]; + static size_t longTermDataSize{ 0u }; +#ifdef SHORT_TERM_ALLOCATOR_SIZE + static char shortTermData[SHORT_TERM_ALLOCATOR_SIZE]; + static size_t shortTermDataSize{ 0u }; +#endif + static Term term{ Term::LONG }; + + constexpr static size_t getAlignedDataSize(const size_t dataSize, const size_t size) + { + const auto alignmentRequirement{ min(size, alignof(max_align_t)) }; + return (dataSize / alignmentRequirement + 1u) * alignmentRequirement; + } + + // Not Thread Safe + static void* longTermAlloc(const size_t size) + { + longTermDataSize = getAlignedDataSize(longTermDataSize, size); + const auto result{ longTermData + longTermDataSize }; + longTermDataSize += size; +#ifdef _DEBUG + cout << "Long term data usage: " << longTermDataSize << " bytes\n"; +#endif + return result; + } + + + // Not Thread Safe + static void* shortTermAlloc(const size_t size) + { +#ifdef SHORT_TERM_ALLOCATOR_SIZE + shortTermDataSize = getAlignedDataSize(shortTermDataSize, size); + const auto result{ shortTermData + shortTermDataSize }; + shortTermDataSize += size; +#ifdef _DEBUG + cout << "Short term data usage: " << shortTermDataSize << " bytes\n"; +#endif + return result; +#else + size; + return nullptr; +#endif + } + +#ifdef SHORT_TERM_ALLOCATOR_SIZE + constexpr void beginShortTermAlloc() + { + term = Term::SHORT; + } + + constexpr void endShortTermAlloc() + { + shortTermDataSize = 0u; + term = Term::LONG; + } +#endif +} + +using ii887522::nitro::Term; +using ii887522::nitro::term; +using ii887522::nitro::longTermAlloc; +using ii887522::nitro::shortTermAlloc; + +// Not Thread Safe +void* operator new(const size_t size) +{ + switch (term) + { + case Term::LONG: return longTermAlloc(size); + case Term::SHORT: return shortTermAlloc(size); + } + throw bad_alloc{ }; +} + +// Not Thread Safe +void operator delete(void*const) { } + +#endif +#endif diff --git a/nitro/src/main/Any/AnimatedAny.h b/nitro/src/main/Any/AnimatedAny.h new file mode 100644 index 0000000..915ce62 --- /dev/null +++ b/nitro/src/main/Any/AnimatedAny.h @@ -0,0 +1,114 @@ +#ifndef II887522_NITRO_ANIMATED_ANY_H +#define II887522_NITRO_ANIMATED_ANY_H + +#include "../Functions/math_ext.h" +#include "../Struct/Range.h" +#include +#include +#include +#include "Reactive.h" +#include + +using std::runtime_error; +using std::string; +using std::function; + +namespace ii887522::nitro +{ + // Param T: it must not be equal to unsigned type + template struct AnimatedAny final + { + // Not Thread Safe + class Builder final + { + // remove copy semantics + Builder(const Builder&) = delete; + Builder& operator=(const Builder&) = delete; + + // remove move semantics + Builder(Builder&&) = delete; + Builder& operator=(Builder&&) = delete; + + const T value; + unsigned int duration; // animation duration + bool hasSetDuration; // has set animation duration + const function onAnimationEnd; + + public: + explicit constexpr Builder(const T& value, const function& onAnimationEnd = []() { }) : value{ value }, duration{ 0u }, + hasSetDuration{ false }, onAnimationEnd{ onAnimationEnd } { } + + // Animation duration + // Param p_value: it must not be assigned to 0 + // Must Call Time(s): At least 1 + constexpr Builder& setDuration(const unsigned int p_value) + { + duration = p_value; + hasSetDuration = true; + return *this; + } + + // Must Call Time(s): At least 1 + AnimatedAny build() + { + if (hasSetDuration) return AnimatedAny{ *this }; + throw runtime_error{ string{ "AnimatedAny<" } + typeid(T).name() + "> duration is required!" }; + } + + friend struct AnimatedAny; + }; + + private: + T start; + T now; + T end; + const unsigned int duration; // animation duration + unsigned int elaspedTime; + const function onAnimationEnd; + + explicit constexpr AnimatedAny(const Builder& builder) : start{ builder.value }, now{ builder.value }, end{ builder.value }, + duration{ builder.duration }, elaspedTime{ 0u }, onAnimationEnd{ builder.onAnimationEnd } { } + + public: + constexpr const T& getStart() const + { + return start; + } + + constexpr const T& get() const + { + return now; + } + + constexpr const T& getEnd() const + { + return end; + } + + constexpr void set(const T& value) + { + start = now; + end = value; + elaspedTime = 0u; + } + + constexpr void teleport(const T& value) + { + start = now; + now = value; + end = value; + elaspedTime = duration; + } + + constexpr void step(const unsigned int dt) + { + if (elaspedTime == duration) return; + elaspedTime += dt; + clamp(elaspedTime, Range{ 0u, duration }); + now = static_cast(start + (end - start) * (static_cast(elaspedTime) / duration)); + if (elaspedTime == duration) onAnimationEnd(); + } + }; +} + +#endif diff --git a/nitro/src/main/Any/Reactive.h b/nitro/src/main/Any/Reactive.h new file mode 100644 index 0000000..ad32038 --- /dev/null +++ b/nitro/src/main/Any/Reactive.h @@ -0,0 +1,47 @@ +#ifndef II887522_NITRO_REACTIVE_H +#define II887522_NITRO_REACTIVE_H + +#include +#include + +using std::function; +using std::vector; + +namespace ii887522::nitro +{ + // Not Thread Safe + template class Reactive + { + // remove copy semantics + Reactive(const Reactive&) = delete; + Reactive& operator=(const Reactive&) = delete; + + // remove move semantics + Reactive(Reactive&&) = delete; + Reactive& operator=(Reactive&&) = delete; + + T value; + vector> handlers; + + public: + explicit constexpr Reactive(const T& value) : value{ value } { } + + constexpr const T& get() const + { + return value; + } + + virtual void set(const T& p_value, const int ignoredHandlerI = -1) + { + value = p_value; + for (auto i{ 0u }; i != handlers.size(); ++i) if (static_cast(i) != ignoredHandlerI) handlers[i](value, i); + } + + constexpr void watch(const function& handler) + { + handlers.push_back(handler); + } + }; +} + +#endif diff --git a/nitro/src/main/Functions/math_ext.h b/nitro/src/main/Functions/math_ext.h new file mode 100644 index 0000000..8947f50 --- /dev/null +++ b/nitro/src/main/Functions/math_ext.h @@ -0,0 +1,35 @@ +#ifndef II887522_NITRO_MATH_EXT_H +#define II887522_NITRO_MATH_EXT_H + +#include "../Struct/Range.h" + +namespace ii887522::nitro +{ + template constexpr void clamp(T& value, const Range& range) + { + if (value < range.min) value = range.min; + else if (value > range.max) value = range.max; + } + + template constexpr bool isOverlapX(const T& x, const Range& xRange) + { + return x >= xRange.min && x < xRange.max; + } + + template constexpr bool isOverlapY(const T& y, const Range& yRange) + { + return y >= yRange.min && y < yRange.max; + } + + template constexpr T min(const T& l, const T& r) + { + return l < r ? l : r; + } + + template constexpr T max(const T& l, const T& r) + { + return l > r ? l : r; + } +} + +#endif diff --git a/nitro/src/main/Functions/queue_ext.h b/nitro/src/main/Functions/queue_ext.h new file mode 100644 index 0000000..30622f2 --- /dev/null +++ b/nitro/src/main/Functions/queue_ext.h @@ -0,0 +1,16 @@ +#ifndef II887522_NITRO_QUEUE_EXT_H +#define II887522_NITRO_QUEUE_EXT_H + +#include + +using std::queue; + +namespace ii887522::nitro +{ + template void clear(queue& queue) + { + while (!queue.empty()) queue.pop(); + } +} + +#endif diff --git a/nitro/src/main/Reactive/BinaryReactive.h b/nitro/src/main/Reactive/BinaryReactive.h new file mode 100644 index 0000000..ea6edbc --- /dev/null +++ b/nitro/src/main/Reactive/BinaryReactive.h @@ -0,0 +1,57 @@ +#ifndef II887522_NITRO_BINARY_REACTIVE_H +#define II887522_NITRO_BINARY_REACTIVE_H + +#include "../Any/Reactive.h" +#include +#include + +using std::vector; +using std::function; + +namespace ii887522::nitro +{ + // Not Thread Safe + template class BinaryReactive final : public Reactive + { + // remove copy semantics + BinaryReactive(const BinaryReactive&) = delete; + BinaryReactive& operator=(const BinaryReactive&) = delete; + + // remove move semantics + BinaryReactive(BinaryReactive&&) = delete; + BinaryReactive& operator=(BinaryReactive&&) = delete; + + vector*> children; + vector> functions; + vector*> thats; + + public: + explicit constexpr BinaryReactive(const T& value) : Reactive{ value } { } + + explicit constexpr BinaryReactive(BinaryReactive*const leftParent, BinaryReactive*const rightParent, + const function& function) : + Reactive{ function(leftParent ? &leftParent->get() : nullptr, rightParent ? &rightParent->get() : nullptr) } + { + if (leftParent) + { + leftParent->children.push_back(this); + leftParent->functions.push_back(function); + leftParent->thats.push_back(rightParent); + } + if (rightParent) + { + rightParent->children.push_back(this); + rightParent->functions.push_back(function); + rightParent->thats.push_back(leftParent); + } + } + + virtual void set(const T& value, const int ignoredHandlerI = -1) override + { + Reactive::set(value, ignoredHandlerI); + for (auto i{ 0u }; i != children.size(); ++i) children[i]->set(functions[i](&this->get(), thats[i] ? &thats[i]->get() : nullptr)); + } + }; +} + +#endif diff --git a/nitro/src/main/Reactive/UnaryReactive.h b/nitro/src/main/Reactive/UnaryReactive.h new file mode 100644 index 0000000..6beab9c --- /dev/null +++ b/nitro/src/main/Reactive/UnaryReactive.h @@ -0,0 +1,46 @@ +#ifndef II887522_NITRO_UNARY_REACTIVE_H +#define II887522_NITRO_UNARY_REACTIVE_H + +#include "../Any/Reactive.h" +#include +#include + +using std::vector; +using std::function; + +namespace ii887522::nitro +{ + // Not Thread Safe + template class UnaryReactive final : public Reactive + { + // remove copy semantics + UnaryReactive(const UnaryReactive&) = delete; + UnaryReactive& operator=(const UnaryReactive&) = delete; + + // remove move semantics + UnaryReactive(UnaryReactive&&) = delete; + UnaryReactive& operator=(UnaryReactive&&) = delete; + + vector*> children; + vector> functions; + + public: + explicit constexpr UnaryReactive(const T& value) : Reactive{ value } { } + + explicit constexpr UnaryReactive(UnaryReactive*const parent, const function& function) : + Reactive{ function(parent ? &parent->get() : nullptr) } + { + if (!parent) return; + parent->children.push_back(this); + parent->functions.push_back(function); + } + + virtual void set(const T& value, const int ignoredHandlerI = -1) override + { + Reactive::set(value, ignoredHandlerI); + for (auto i{ 0u }; i != children.size(); ++i) children[i]->set(functions[i](&this->get())); + } + }; +} + +#endif diff --git a/nitro/src/main/Struct/Range.h b/nitro/src/main/Struct/Range.h new file mode 100644 index 0000000..d3dba27 --- /dev/null +++ b/nitro/src/main/Struct/Range.h @@ -0,0 +1,24 @@ +#ifndef II887522_NITRO_RANGE_H +#define II887522_NITRO_RANGE_H + +namespace ii887522::nitro +{ + template struct Range final + { + // remove copy semantics + Range(const Range&) = delete; + Range& operator=(const Range&) = delete; + + // remove move semantics + Range(Range&&) = delete; + Range& operator=(Range&&) = delete; + + const T min; + const T max; + + public: + explicit constexpr Range(const T& min, const T& max) : min{ min }, max{ max } { } + }; +} + +#endif diff --git a/nitro/src/main/Struct/Vector.h b/nitro/src/main/Struct/Vector.h new file mode 100644 index 0000000..ebf0ba7 --- /dev/null +++ b/nitro/src/main/Struct/Vector.h @@ -0,0 +1,20 @@ +#ifndef II887522_NITRO_VECTOR_H +#define II887522_NITRO_VECTOR_H + +namespace ii887522::nitro +{ + template struct Vector final + { + T x; + T y; + + explicit constexpr Vector(const T& x, const T& y) : x{ x }, y{ y } { } + + template constexpr Vector operator*(const U& scale) const + { + return Vector{ static_cast(x * scale), static_cast(y * scale) }; + } + }; +} + +#endif diff --git a/nitro/src/test/Any/AnimatedAny.test.cpp b/nitro/src/test/Any/AnimatedAny.test.cpp new file mode 100644 index 0000000..808f3df --- /dev/null +++ b/nitro/src/test/Any/AnimatedAny.test.cpp @@ -0,0 +1,244 @@ +#ifdef TEST + +#include "AnimatedAny.test.h" +#include +#include "../../main/Any/AnimatedAny.h" +#include "../../main/Any/Reactive.h" +#include + +using std::runtime_error; + +namespace ii887522::nitro +{ + static void testBuild() + { + assert(AnimatedAny::Builder{ 0 }.setDuration(250u).build().get() == 0); + assert(AnimatedAny::Builder{ 1 }.setDuration(250u).build().get() == 1); + assert(AnimatedAny::Builder{ 1 }.setDuration(500u).build().get() == 1); + { + auto n{ 0u }; + assert((AnimatedAny::Builder{ 1, [&n]() { + ++n; + } }.setDuration(500u).build().get() == 1)); + assert(n == 0u); + } + try + { + AnimatedAny::Builder{ 0 }.build(); + } + catch (const runtime_error&) + { + try + { + AnimatedAny::Builder{ 1 }.build(); + } + catch (const runtime_error&) + { + try + { + auto n{ 0u }; + AnimatedAny::Builder{ 1, [&n]() { + ++n; + } }.build(); + } + catch (const runtime_error&) + { + return; + } + } + } + assert(false); + } + + static void testTeleport() + { + { + AnimatedAny n{ AnimatedAny::Builder{ 0 }.setDuration(250u).build() }; + n.teleport(1); + assert(n.getStart() == 0); + assert(n.get() == 1); + assert(n.getEnd() == 1); + n.teleport(2); + assert(n.getStart() == 1); + assert(n.get() == 2); + assert(n.getEnd() == 2); + } + { + AnimatedAny n{ AnimatedAny::Builder{ 10 }.setDuration(250u).build() }; + n.teleport(1); + assert(n.getStart() == 10); + assert(n.get() == 1); + assert(n.getEnd() == 1); + n.teleport(2); + assert(n.getStart() == 1); + assert(n.get() == 2); + assert(n.getEnd() == 2); + } + { + AnimatedAny n{ AnimatedAny::Builder{ 10 }.setDuration(500u).build() }; + n.teleport(1); + assert(n.getStart() == 10); + assert(n.get() == 1); + assert(n.getEnd() == 1); + n.teleport(2); + assert(n.getStart() == 1); + assert(n.get() == 2); + assert(n.getEnd() == 2); + } + { + auto m{ 0u }; + AnimatedAny n{ AnimatedAny::Builder{ 10, [&m]() { + ++m; + } }.setDuration(500u).build() }; + n.teleport(1); + assert(n.getStart() == 10); + assert(n.get() == 1); + assert(n.getEnd() == 1); + assert(m == 0u); + n.teleport(2); + assert(n.getStart() == 1); + assert(n.get() == 2); + assert(n.getEnd() == 2); + assert(m == 0u); + } + } + + static void testStep() + { + { + AnimatedAny n{ AnimatedAny::Builder{ 0 }.setDuration(250u).build() }; + n.set(100); + n.step(0u); + assert(n.getStart() == 0); + assert(n.get() == 0); + assert(n.getEnd() == 100); + n.step(30u); + assert(n.getStart() == 0); + assert(n.get() == 12); + assert(n.getEnd() == 100); + n.step(40u); + assert(n.getStart() == 0); + assert(n.get() == 28); + assert(n.getEnd() == 100); + n.step(50u); + assert(n.getStart() == 0); + assert(n.get() == 48); + assert(n.getEnd() == 100); + n.step(60u); + assert(n.getStart() == 0); + assert(n.get() == 72); + assert(n.getEnd() == 100); + n.step(70u); + assert(n.getStart() == 0); + assert(n.get() == 100); + assert(n.getEnd() == 100); + } + { + AnimatedAny n{ AnimatedAny::Builder{ 10 }.setDuration(250u).build() }; + n.set(110); + n.step(0u); + assert(n.getStart() == 10); + assert(n.get() == 10); + assert(n.getEnd() == 110); + n.step(30u); + assert(n.getStart() == 10); + assert(n.get() == 22); + assert(n.getEnd() == 110); + n.step(40u); + assert(n.getStart() == 10); + assert(n.get() == 38); + assert(n.getEnd() == 110); + n.step(50u); + assert(n.getStart() == 10); + assert(n.get() == 58); + assert(n.getEnd() == 110); + n.step(60u); + assert(n.getStart() == 10); + assert(n.get() == 82); + assert(n.getEnd() == 110); + n.step(70u); + assert(n.getStart() == 10); + assert(n.get() == 110); + assert(n.getEnd() == 110); + } + { + AnimatedAny n{ AnimatedAny::Builder{ 10 }.setDuration(500u).build() }; + n.set(110); + n.step(0u); + assert(n.getStart() == 10); + assert(n.get() == 10); + assert(n.getEnd() == 110); + n.step(60u); + assert(n.getStart() == 10); + assert(n.get() == 22); + assert(n.getEnd() == 110); + n.step(80u); + assert(n.getStart() == 10); + assert(n.get() == 38); + assert(n.getEnd() == 110); + n.step(100u); + assert(n.getStart() == 10); + assert(n.get() == 58); + assert(n.getEnd() == 110); + n.step(120u); + assert(n.getStart() == 10); + assert(n.get() == 82); + assert(n.getEnd() == 110); + n.step(140u); + assert(n.getStart() == 10); + assert(n.get() == 110); + assert(n.getEnd() == 110); + } + { + auto m{ 0u }; + AnimatedAny n{ AnimatedAny::Builder{ 10, [&m]() { + ++m; + } }.setDuration(500u).build() }; + n.set(110); + n.step(0u); + assert(n.getStart() == 10); + assert(n.get() == 10); + assert(n.getEnd() == 110); + assert(m == 0u); + n.step(60u); + assert(n.getStart() == 10); + assert(n.get() == 22); + assert(n.getEnd() == 110); + assert(m == 0u); + n.step(80u); + assert(n.getStart() == 10); + assert(n.get() == 38); + assert(n.getEnd() == 110); + assert(m == 0u); + n.step(100u); + assert(n.getStart() == 10); + assert(n.get() == 58); + assert(n.getEnd() == 110); + assert(m == 0u); + n.step(120u); + assert(n.getStart() == 10); + assert(n.get() == 82); + assert(n.getEnd() == 110); + assert(m == 0u); + n.step(140u); + assert(n.getStart() == 10); + assert(n.get() == 110); + assert(n.getEnd() == 110); + assert(m == 1u); + n.step(10u); + assert(n.getStart() == 10); + assert(n.get() == 110); + assert(n.getEnd() == 110); + assert(m == 1u); + } + } + + void testAnimatedAny() + { + testBuild(); + testTeleport(); + testStep(); + } +} + +#endif diff --git a/nitro/src/test/Any/AnimatedAny.test.h b/nitro/src/test/Any/AnimatedAny.test.h new file mode 100644 index 0000000..1d60e8f --- /dev/null +++ b/nitro/src/test/Any/AnimatedAny.test.h @@ -0,0 +1,12 @@ +#ifdef TEST + +#ifndef II887522_NITRO_ANIMATED_ANY_TEST_H +#define II887522_NITRO_ANIMATED_ANY_TEST_H + +namespace ii887522::nitro +{ + void testAnimatedAny(); +} + +#endif +#endif diff --git a/nitro/src/test/Any/Reactive.test.cpp b/nitro/src/test/Any/Reactive.test.cpp new file mode 100644 index 0000000..9881f48 --- /dev/null +++ b/nitro/src/test/Any/Reactive.test.cpp @@ -0,0 +1,69 @@ +#ifdef TEST + +#include "Reactive.test.h" +#include "../../main/Any/Reactive.h" +#include + +namespace ii887522::nitro +{ + static void testSet() + { + { + Reactive n{ 0u }; + n.set(1u); + assert(n.get() == 1u); + auto count{ 0u }; + n.watch([&count](const unsigned int& value, const int) { + count += value; + }); + n.set(2u); + assert(n.get() == 2u); + assert(count == 2u); + n.watch([&count](const unsigned int& value, const int) { + count += value; + }); + n.set(3u); + assert(n.get() == 3u); + assert(count == 8u); + n.watch([&n, &count](const unsigned int& value, const int handlerI) { + count += value; + n.set(count, handlerI); + }); + n.set(4u); + assert(n.get() == 20u); + assert(count == 60u); + } + { + Reactive n{ 2u }; + n.set(1u); + assert(n.get() == 1u); + auto count{ 0u }; + n.watch([&count](const unsigned int& value, const int) { + count += value; + }); + n.set(2u); + assert(n.get() == 2u); + assert(count == 2u); + n.watch([&count](const unsigned int& value, const int) { + count += value; + }); + n.set(3u); + assert(n.get() == 3u); + assert(count == 8u); + n.watch([&n, &count](const unsigned int& value, const int handlerI) { + count += value; + n.set(count, handlerI); + }); + n.set(4u); + assert(n.get() == 20u); + assert(count == 60u); + } + } + + void testReactive() + { + testSet(); + } +} + +#endif diff --git a/nitro/src/test/Any/Reactive.test.h b/nitro/src/test/Any/Reactive.test.h new file mode 100644 index 0000000..18e34f2 --- /dev/null +++ b/nitro/src/test/Any/Reactive.test.h @@ -0,0 +1,12 @@ +#ifdef TEST + +#ifndef II887522_NITRO_REACTIVE_TEST_H +#define II887522_NITRO_REACTIVE_TEST_H + +namespace ii887522::nitro +{ + void testReactive(); +} + +#endif +#endif diff --git a/nitro/src/test/Functions/math_ext.test.cpp b/nitro/src/test/Functions/math_ext.test.cpp new file mode 100644 index 0000000..546475f --- /dev/null +++ b/nitro/src/test/Functions/math_ext.test.cpp @@ -0,0 +1,118 @@ +#ifdef TEST + +#include "math_ext.test.h" +#include +#include "../../main/Functions/math_ext.h" +#include "../../main/Struct/Range.h" + +namespace ii887522::nitro +{ + static void testClamp() + { + { + auto n{ 0u }; + clamp(n, Range{ 1u, 3u }); + assert(n == 1u); + } + { + auto n{ 1u }; + clamp(n, Range{ 1u, 3u }); + assert(n == 1u); + } + { + auto n{ 2u }; + clamp(n, Range{ 1u, 3u }); + assert(n == 2u); + } + { + auto n{ 3u }; + clamp(n, Range{ 1u, 3u }); + assert(n == 3u); + } + { + auto n{ 4u }; + clamp(n, Range{ 1u, 3u }); + assert(n == 3u); + } + { + auto n{ 0u }; + clamp(n, Range{ 2u, 6u }); + assert(n == 2u); + } + { + auto n{ 2u }; + clamp(n, Range{ 2u, 6u }); + assert(n == 2u); + } + { + auto n{ 4u }; + clamp(n, Range{ 2u, 6u }); + assert(n == 4u); + } + { + auto n{ 6u }; + clamp(n, Range{ 2u, 6u }); + assert(n == 6u); + } + { + auto n{ 8u }; + clamp(n, Range{ 2u, 6u }); + assert(n == 6u); + } + } + + constexpr static void testIsOverlapX() + { + static_assert(!isOverlapX(0u, Range{ 1u, 3u })); + static_assert(isOverlapX(1u, Range{ 1u, 3u })); + static_assert(isOverlapX(2u, Range{ 1u, 3u })); + static_assert(!isOverlapX(3u, Range{ 1u, 3u })); + static_assert(!isOverlapX(4u, Range{ 1u, 3u })); + static_assert(!isOverlapX(0u, Range{ 2u, 6u })); + static_assert(isOverlapX(2u, Range{ 2u, 6u })); + static_assert(isOverlapX(4u, Range{ 2u, 6u })); + static_assert(!isOverlapX(6u, Range{ 2u, 6u })); + static_assert(!isOverlapX(8u, Range{ 2u, 6u })); + } + + constexpr static void testIsOverlapY() + { + static_assert(!isOverlapY(0u, Range{ 1u, 3u })); + static_assert(isOverlapY(1u, Range{ 1u, 3u })); + static_assert(isOverlapY(2u, Range{ 1u, 3u })); + static_assert(!isOverlapY(3u, Range{ 1u, 3u })); + static_assert(!isOverlapY(4u, Range{ 1u, 3u })); + static_assert(!isOverlapY(0u, Range{ 2u, 6u })); + static_assert(isOverlapY(2u, Range{ 2u, 6u })); + static_assert(isOverlapY(4u, Range{ 2u, 6u })); + static_assert(!isOverlapY(6u, Range{ 2u, 6u })); + static_assert(!isOverlapY(8u, Range{ 2u, 6u })); + } + + constexpr static void testMin() + { + static_assert(min(0u, 0u) == 0u); + static_assert(min(1u, 0u) == 0u); + static_assert(min(1u, 1u) == 1u); + static_assert(min(1u, 2u) == 1u); + } + + constexpr static void testMax() + { + static_assert(max(0u, 0u) == 0u); + static_assert(max(1u, 0u) == 1u); + static_assert(max(1u, 1u) == 1u); + static_assert(max(1u, 2u) == 2u); + } + + void testMathExt() + { + testClamp(); + testIsOverlapX(); + testIsOverlapY(); + testMin(); + testMax(); + } +} + +#endif diff --git a/nitro/src/test/Functions/math_ext.test.h b/nitro/src/test/Functions/math_ext.test.h new file mode 100644 index 0000000..59fbfcd --- /dev/null +++ b/nitro/src/test/Functions/math_ext.test.h @@ -0,0 +1,12 @@ +#ifdef TEST + +#ifndef II887522_NITRO_MATH_EXT_TEST_H +#define II887522_NITRO_MATH_EXT_TEST_H + +namespace ii887522::nitro +{ + void testMathExt(); +} + +#endif +#endif diff --git a/nitro/src/test/Functions/queue_ext.test.cpp b/nitro/src/test/Functions/queue_ext.test.cpp new file mode 100644 index 0000000..caf22a5 --- /dev/null +++ b/nitro/src/test/Functions/queue_ext.test.cpp @@ -0,0 +1,41 @@ +#ifdef TEST + +#include "queue_ext.test.h" +#include "../../main/Functions/queue_ext.h" +#include +#include + +using std::queue; + +namespace ii887522::nitro +{ + static void testClear() + { + queue queue; + clear(queue); + assert(queue.empty()); + assert(queue.size() == 0u); + queue.push(1u); + clear(queue); + assert(queue.empty()); + assert(queue.size() == 0u); + queue.push(2u); + queue.push(3u); + clear(queue); + assert(queue.empty()); + assert(queue.size() == 0u); + queue.push(4u); + queue.push(5u); + queue.push(6u); + clear(queue); + assert(queue.empty()); + assert(queue.size() == 0u); + } + + void testQueueExt() + { + testClear(); + } +} + +#endif diff --git a/nitro/src/test/Functions/queue_ext.test.h b/nitro/src/test/Functions/queue_ext.test.h new file mode 100644 index 0000000..d65ee24 --- /dev/null +++ b/nitro/src/test/Functions/queue_ext.test.h @@ -0,0 +1,12 @@ +#ifdef TEST + +#ifndef II887522_NITRO_QUEUE_EXT_TEST_H +#define II887522_NITRO_QUEUE_EXT_TEST_H + +namespace ii887522::nitro +{ + void testQueueExt(); +} + +#endif +#endif diff --git a/nitro/src/test/Functions/test.cpp b/nitro/src/test/Functions/test.cpp new file mode 100644 index 0000000..b433ea4 --- /dev/null +++ b/nitro/src/test/Functions/test.cpp @@ -0,0 +1,31 @@ +#ifdef TEST + +#include "../Struct/Vector.test.h" +#include "math_ext.test.h" +#include "../Any/AnimatedAny.test.h" +#include "../Any/Reactive.test.h" +#include "../Functions/queue_ext.test.h" +#include "../Reactive/UnaryReactive.test.h" +#include "../Reactive/BinaryReactive.test.h" + +namespace ii887522::nitro +{ + static int main() + { + testVector(); + testMathExt(); + testAnimatedAny(); + testReactive(); + testQueueExt(); + testUnaryReactive(); + testBinaryReactive(); + return 0; + } +} + +int main() +{ + return ii887522::nitro::main(); +} + +#endif diff --git a/nitro/src/test/Reactive/BinaryReactive.test.cpp b/nitro/src/test/Reactive/BinaryReactive.test.cpp new file mode 100644 index 0000000..deefda6 --- /dev/null +++ b/nitro/src/test/Reactive/BinaryReactive.test.cpp @@ -0,0 +1,198 @@ +#ifdef TEST + +#include "BinaryReactive.test.h" +#include "../../main/Reactive/BinaryReactive.h" +#include +#include + +namespace ii887522::nitro +{ + static void testSet() + { + { + BinaryReactive m{ 0u }; + m.set(1u); + assert(m.get() == 1u); + BinaryReactive n{ 1u }; + n.set(2u); + assert(n.get() == 2u); + BinaryReactive p{ + &m, &n, [](const unsigned int*const left, const unsigned int*const right) { + return *left + *right; + } + }; + m.set(2u); + assert(m.get() == 2u); + assert(p.get() == 4u); + n.set(3u); + assert(n.get() == 3u); + assert(p.get() == 5u); + BinaryReactive q{ + &m, &n, [](const unsigned int*const left, const unsigned int*const right) { + return *left * *right; + } + }; + m.set(3u); + assert(m.get() == 3u); + assert(p.get() == 6u); + assert(q.get() == 9u); + n.set(4u); + assert(n.get() == 4u); + assert(p.get() == 7u); + assert(q.get() == 12u); + BinaryReactive r{ + &m, &n, [](const unsigned int*const left, const unsigned int*const right) { + return static_cast(pow(*left, *right)); + } + }; + m.set(4u); + assert(m.get() == 4u); + assert(p.get() == 8u); + assert(q.get() == 16u); + assert(r.get() == 256u); + n.set(5u); + assert(n.get() == 5u); + assert(p.get() == 9u); + assert(q.get() == 20u); + assert(r.get() == 625u); + + BinaryReactive s{ + &m, nullptr, [](const unsigned int*const left, const unsigned int*const) { + return *left; + } + }; + m.set(5u); + assert(m.get() == 5u); + assert(p.get() == 10u); + assert(q.get() == 25u); + assert(r.get() == 3125u); + assert(s.get() == 5u); + n.set(6u); + assert(n.get() == 6u); + assert(p.get() == 11u); + assert(q.get() == 30u); + assert(r.get() == 7776u); + assert(s.get() == 5u); + BinaryReactive t{ + nullptr, &n, [](const unsigned int*const, const unsigned int*const) { + return 0u; + } + }; + m.set(6u); + assert(m.get() == 6u); + assert(p.get() == 12u); + assert(q.get() == 36u); + assert(r.get() == 46656u); + assert(s.get() == 6u); + assert(t.get() == 0u); + n.set(7u); + assert(n.get() == 7u); + assert(p.get() == 13u); + assert(q.get() == 42u); + assert(r.get() == 117649u); + assert(s.get() == 6u); + assert(t.get() == 0u); + BinaryReactive u{ + nullptr, nullptr, [](const unsigned int*const, const unsigned int*const) { + return 1u; + } + }; + } + { + BinaryReactive m{ 2u }; + m.set(1u); + assert(m.get() == 1u); + BinaryReactive n{ 3u }; + n.set(2u); + assert(n.get() == 2u); + BinaryReactive p{ + &m, &n, [](const unsigned int*const left, const unsigned int*const right) { + return *left + *right; + } + }; + m.set(2u); + assert(m.get() == 2u); + assert(p.get() == 4u); + n.set(3u); + assert(n.get() == 3u); + assert(p.get() == 5u); + BinaryReactive q{ + &m, &n, [](const unsigned int*const left, const unsigned int*const right) { + return *left * *right; + } + }; + m.set(3u); + assert(m.get() == 3u); + assert(p.get() == 6u); + assert(q.get() == 9u); + n.set(4u); + assert(n.get() == 4u); + assert(p.get() == 7u); + assert(q.get() == 12u); + BinaryReactive r{ + &m, &n, [](const unsigned int*const left, const unsigned int*const right) { + return static_cast(pow(*left, *right)); + } + }; + m.set(4u); + assert(m.get() == 4u); + assert(p.get() == 8u); + assert(q.get() == 16u); + assert(r.get() == 256u); + n.set(5u); + assert(n.get() == 5u); + assert(p.get() == 9u); + assert(q.get() == 20u); + assert(r.get() == 625u); + + BinaryReactive s{ + &m, nullptr, [](const unsigned int*const left, const unsigned int*const) { + return *left; + } + }; + m.set(5u); + assert(m.get() == 5u); + assert(p.get() == 10u); + assert(q.get() == 25u); + assert(r.get() == 3125u); + assert(s.get() == 5u); + n.set(6u); + assert(n.get() == 6u); + assert(p.get() == 11u); + assert(q.get() == 30u); + assert(r.get() == 7776u); + assert(s.get() == 5u); + BinaryReactive t{ + nullptr, &n, [](const unsigned int*const, const unsigned int*const) { + return 0u; + } + }; + m.set(6u); + assert(m.get() == 6u); + assert(p.get() == 12u); + assert(q.get() == 36u); + assert(r.get() == 46656u); + assert(s.get() == 6u); + assert(t.get() == 0u); + n.set(7u); + assert(n.get() == 7u); + assert(p.get() == 13u); + assert(q.get() == 42u); + assert(r.get() == 117649u); + assert(s.get() == 6u); + assert(t.get() == 0u); + BinaryReactive u{ + nullptr, nullptr, [](const unsigned int* const, const unsigned int* const) { + return 1u; + } + }; + } + } + + void testBinaryReactive() + { + testSet(); + } +} + +#endif diff --git a/nitro/src/test/Reactive/BinaryReactive.test.h b/nitro/src/test/Reactive/BinaryReactive.test.h new file mode 100644 index 0000000..e8e2923 --- /dev/null +++ b/nitro/src/test/Reactive/BinaryReactive.test.h @@ -0,0 +1,12 @@ +#ifdef TEST + +#ifndef II887522_NITRO_BINARY_REACTIVE_TEST_H +#define II887522_NITRO_BINARY_REACTIVE_TEST_H + +namespace ii887522::nitro +{ + void testBinaryReactive(); +} + +#endif +#endif diff --git a/nitro/src/test/Reactive/UnaryReactive.test.cpp b/nitro/src/test/Reactive/UnaryReactive.test.cpp new file mode 100644 index 0000000..2c257ce --- /dev/null +++ b/nitro/src/test/Reactive/UnaryReactive.test.cpp @@ -0,0 +1,78 @@ +#ifdef TEST + +#include "UnaryReactive.test.h" +#include "../../main/Reactive/UnaryReactive.h" +#include +#include + +namespace ii887522::nitro +{ + static void testSet() + { + { + UnaryReactive n{ 0u }; + n.set(1u); + assert(n.get() == 1u); + UnaryReactive nx{ &n, [](const unsigned int*const value) { + return *value + *value; + } }; + n.set(2u); + assert(n.get() == 2u); + assert(nx.get() == 4u); + UnaryReactive ny{ &n, [](const unsigned int*const value) { + return *value * *value; + } }; + n.set(3u); + assert(n.get() == 3u); + assert(nx.get() == 6u); + assert(ny.get() == 9u); + UnaryReactive nz{ &n, [](const unsigned int*const value) { + return static_cast(sqrt(*value)); + } }; + n.set(4u); + assert(n.get() == 4u); + assert(nx.get() == 8u); + assert(ny.get() == 16u); + assert(nz.get() == 2u); + UnaryReactive nw{ nullptr, [](const unsigned int*const) { + return 0u; + } }; + } + { + UnaryReactive n{ 2u }; + n.set(1u); + assert(n.get() == 1u); + UnaryReactive nx{ &n, [](const unsigned int*const value) { + return *value + *value; + } }; + n.set(2u); + assert(n.get() == 2u); + assert(nx.get() == 4u); + UnaryReactive ny{ &n, [](const unsigned int*const value) { + return *value * *value; + } }; + n.set(3u); + assert(n.get() == 3u); + assert(nx.get() == 6u); + assert(ny.get() == 9u); + UnaryReactive nz{ &n, [](const unsigned int*const value) { + return static_cast(sqrt(*value)); + } }; + n.set(4u); + assert(n.get() == 4u); + assert(nx.get() == 8u); + assert(ny.get() == 16u); + assert(nz.get() == 2u); + UnaryReactive nw{ nullptr, [](const unsigned int*const) { + return 0u; + } }; + } + } + + void testUnaryReactive() + { + testSet(); + } +} + +#endif diff --git a/nitro/src/test/Reactive/UnaryReactive.test.h b/nitro/src/test/Reactive/UnaryReactive.test.h new file mode 100644 index 0000000..2721c19 --- /dev/null +++ b/nitro/src/test/Reactive/UnaryReactive.test.h @@ -0,0 +1,12 @@ +#ifdef TEST + +#ifndef II887522_NITRO_UNARY_REACTIVE_TEST_H +#define II887522_NITRO_UNARY_REACTIVE_TEST_H + +namespace ii887522::nitro +{ + void testUnaryReactive(); +} + +#endif +#endif diff --git a/nitro/src/test/Struct/Vector.test.cpp b/nitro/src/test/Struct/Vector.test.cpp new file mode 100644 index 0000000..d296a82 --- /dev/null +++ b/nitro/src/test/Struct/Vector.test.cpp @@ -0,0 +1,22 @@ +#ifdef TEST + +#include "Vector.test.h" +#include "../../main/Struct/Vector.h" + +namespace ii887522::nitro +{ + constexpr static void testMultiplication() + { + static_assert((Vector{ 1u, 2u } * 0u).x == 0u); + static_assert((Vector{ 3u, 4u } * 1u).y == 4u); + static_assert((Vector{ 5u, 6u } * 2u).x == 10u); + static_assert((Vector{ 7u, 8u } * 3u).y == 24u); + } + + void testVector() + { + testMultiplication(); + } +} + +#endif diff --git a/nitro/src/test/Struct/Vector.test.h b/nitro/src/test/Struct/Vector.test.h new file mode 100644 index 0000000..18ec28c --- /dev/null +++ b/nitro/src/test/Struct/Vector.test.h @@ -0,0 +1,12 @@ +#ifdef TEST + +#ifndef II887522_NITRO_VECTOR_TEST_H +#define II887522_NITRO_VECTOR_TEST_H + +namespace ii887522::nitro +{ + void testVector(); +} + +#endif +#endif diff --git a/nitro/src/test/test.cpp b/nitro/src/test/test.cpp deleted file mode 100644 index 1496e06..0000000 --- a/nitro/src/test/test.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifdef TEST - -namespace ii887522::nitro -{ - static int main() - { - - return 0; - } -} - -int main() -{ - return ii887522::nitro::main(); -} - -#endif