Fixed crash in message dispatcher after 'meta unload'.
Various cosmetic changes.
This commit is contained in:
parent
9720a63401
commit
ff6c56aeac
37 changed files with 949 additions and 602 deletions
|
|
@ -13,14 +13,12 @@
|
|||
#define CR_NAMESPACE_BEGIN namespace cr {
|
||||
#define CR_NAMESPACE_END }
|
||||
|
||||
// undef base max
|
||||
#if defined (max)
|
||||
# undef max
|
||||
#endif
|
||||
|
||||
// undef base min
|
||||
#if defined (min)
|
||||
# undef min
|
||||
// disable microsoft deprecation warning
|
||||
#if defined (_MSC_VER)
|
||||
# if !defined (_CRT_SECURE_NO_DEPRECATE)
|
||||
# define _CRT_SECURE_NO_DEPRECATE
|
||||
# define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -34,13 +32,13 @@ CR_NAMESPACE_BEGIN
|
|||
// some useful type definitions
|
||||
//
|
||||
namespace types {
|
||||
using int8 = signed char;
|
||||
using int16 = signed short;
|
||||
using int32 = signed int;
|
||||
using uint8 = unsigned char;
|
||||
using uint16 = unsigned short;
|
||||
using uint32 = unsigned int;
|
||||
using uint64 = unsigned long long;
|
||||
using int8 = signed char;
|
||||
using int16 = signed short;
|
||||
using int32 = signed int;
|
||||
using uint8 = unsigned char;
|
||||
using uint16 = unsigned short;
|
||||
using uint32 = unsigned int;
|
||||
using uint64 = unsigned long long;
|
||||
}
|
||||
|
||||
// make types available for our own use
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ CR_NAMESPACE_BEGIN
|
|||
// template for hashing our string
|
||||
template <typename K> struct StringHash {
|
||||
uint32 operator () (const K &key) const {
|
||||
char *str = const_cast <char *> (key.chars ());
|
||||
auto str = const_cast <char *> (key.chars ());
|
||||
uint32 hash = 0;
|
||||
|
||||
while (*str++) {
|
||||
|
|
@ -68,6 +68,7 @@ namespace detail {
|
|||
template <class K, class V, class H = StringHash <K>, size_t HashSize = 36> class Dictionary final : public DenyCopying {
|
||||
private:
|
||||
using DictBucket = detail::DictionaryBucket <K, V>;
|
||||
using DictList = detail::DictionaryList;
|
||||
|
||||
public:
|
||||
enum : size_t {
|
||||
|
|
@ -75,7 +76,7 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
Array <detail::DictionaryList *> m_table;
|
||||
Array <DictList *> m_table;
|
||||
Array <DictBucket> m_buckets;
|
||||
H m_hasher;
|
||||
|
||||
|
|
@ -98,7 +99,7 @@ private:
|
|||
size_t created = m_buckets.length ();
|
||||
m_buckets.resize (created + 1);
|
||||
|
||||
auto allocated = alloc.allocate <detail::DictionaryList> ();
|
||||
auto allocated = alloc.allocate <DictList> ();
|
||||
|
||||
allocated->index = created;
|
||||
allocated->next = m_table[pos];
|
||||
|
|
@ -163,7 +164,7 @@ public:
|
|||
auto pos = hashed % m_table.length ();
|
||||
auto *bucket = m_table[pos];
|
||||
|
||||
detail::DictionaryList *next = nullptr;
|
||||
DictList *next = nullptr;
|
||||
|
||||
while (bucket != nullptr) {
|
||||
if (m_buckets[bucket->index].hash == hashed) {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ public:
|
|||
public:
|
||||
|
||||
bool open (const String &file, const String &mode) {
|
||||
if (*this) {
|
||||
close ();
|
||||
}
|
||||
|
||||
if ((m_handle = fopen (file.chars (), mode.chars ())) == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,15 +20,25 @@ CR_NAMESPACE_BEGIN
|
|||
class SimpleHook : DenyCopying {
|
||||
private:
|
||||
enum : uint32 {
|
||||
CodeLength = 12
|
||||
#if defined (CR_ARCH_X64)
|
||||
CodeLength = 14
|
||||
#else
|
||||
CodeLength = 6
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined (CR_ARCH_X64)
|
||||
using uint = uint64;
|
||||
#else
|
||||
using uint = uint32;
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool m_patched;
|
||||
|
||||
uint32 m_pageSize;
|
||||
uint32 m_origFunc;
|
||||
uint32 m_hookFunc;
|
||||
uint m_pageSize;
|
||||
uint m_origFunc;
|
||||
uint m_hookFunc;
|
||||
|
||||
uint8 m_origBytes[CodeLength] {};
|
||||
uint8 m_hookBytes[CodeLength] {};
|
||||
|
|
@ -43,11 +53,13 @@ private:
|
|||
#else
|
||||
m_pageSize = sysconf (_SC_PAGESIZE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
inline void *align (void *address) {
|
||||
#if !defined (CR_WINDOWS)
|
||||
void *align (void *address) {
|
||||
return reinterpret_cast <void *> ((reinterpret_cast <long> (address) & ~(m_pageSize - 1)));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool unprotect () {
|
||||
auto orig = reinterpret_cast <void *> (m_origFunc);
|
||||
|
|
@ -74,25 +86,36 @@ public:
|
|||
|
||||
public:
|
||||
bool patch (void *address, void *replacement) {
|
||||
if (plat.isArm) {
|
||||
const uint16 jmp = 0x25ff;
|
||||
|
||||
if (plat.arm) {
|
||||
return false;
|
||||
}
|
||||
uint8 *ptr = reinterpret_cast <uint8 *> (address);
|
||||
auto ptr = reinterpret_cast <uint8 *> (address);
|
||||
|
||||
while (*reinterpret_cast <uint16 *> (ptr) == 0x25ff) {
|
||||
ptr = **reinterpret_cast <uint8 * **> ((ptr + 2));
|
||||
while (*reinterpret_cast <uint16 *> (ptr) == jmp) {
|
||||
ptr = **reinterpret_cast <uint8 * **> (ptr + 2);
|
||||
}
|
||||
m_origFunc = reinterpret_cast <uint32> (ptr);
|
||||
m_origFunc = reinterpret_cast <uint> (address);
|
||||
|
||||
if (!m_origFunc) {
|
||||
return false;
|
||||
}
|
||||
m_hookFunc = reinterpret_cast <uint32> (replacement);
|
||||
m_hookFunc = reinterpret_cast <uint> (replacement);
|
||||
|
||||
m_hookBytes[0] = 0x68;
|
||||
m_hookBytes[5] = 0xc3;
|
||||
if (plat.x64) {
|
||||
const uint16 nop = 0x00000000;
|
||||
|
||||
*reinterpret_cast <uint32 *> (&m_hookBytes[1]) = m_hookFunc;
|
||||
memcpy (&m_hookBytes[0], &jmp, sizeof (uint16));
|
||||
memcpy (&m_hookBytes[2], &nop, sizeof (uint16));
|
||||
memcpy (&m_hookBytes[6], &replacement, sizeof (uint));
|
||||
}
|
||||
else {
|
||||
m_hookBytes[0] = 0x68;
|
||||
m_hookBytes[5] = 0xc3;
|
||||
|
||||
memcpy (&m_hookBytes[1], &m_hookFunc, sizeof (uint));
|
||||
}
|
||||
|
||||
if (unprotect ()) {
|
||||
memcpy (m_origBytes, reinterpret_cast <void *> (m_origFunc), CodeLength);
|
||||
|
|
@ -130,6 +153,6 @@ public:
|
|||
bool enabled () const {
|
||||
return m_patched;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -374,19 +374,19 @@ public:
|
|||
if (boundarySlash != String::InvalidIndex) {
|
||||
boundaryName = localPath.substr (boundarySlash + 1);
|
||||
}
|
||||
const String &kBoundary = "---crlib_upload_boundary_1337";
|
||||
const String &boundaryLine = "---crlib_upload_boundary_1337";
|
||||
|
||||
String request, start, end;
|
||||
start.appendf ("--%s\r\n", kBoundary.chars ());
|
||||
start.appendf ("--%s\r\n", boundaryLine.chars ());
|
||||
start.appendf ("Content-Disposition: form-data; name='file'; filename='%s'\r\n", boundaryName.chars ());
|
||||
start.append ("Content-Type: application/octet-stream\r\n\r\n");
|
||||
|
||||
end.appendf ("\r\n--%s--\r\n\r\n", kBoundary.chars ());
|
||||
end.appendf ("\r\n--%s--\r\n\r\n", boundaryLine.chars ());
|
||||
|
||||
request.appendf ("POST /%s HTTP/1.1\r\n", uri.path.chars ());
|
||||
request.appendf ("Host: %s\r\n", uri.host.chars ());
|
||||
request.appendf ("User-Agent: %s\r\n", m_userAgent.chars ());
|
||||
request.appendf ("Content-Type: multipart/form-data; boundary=%s\r\n", kBoundary.chars ());
|
||||
request.appendf ("Content-Type: multipart/form-data; boundary=%s\r\n", boundaryLine.chars ());
|
||||
request.appendf ("Content-Length: %d\r\n\r\n", file.length () + start.length () + end.length ());
|
||||
|
||||
// send the main request
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ private:
|
|||
}
|
||||
|
||||
UniquePtr <LambdaFunctorWrapper> clone () const override {
|
||||
return createUniqueBase <LambdaFunctor <T>, LambdaFunctorWrapper> (m_callable);
|
||||
return makeUnique <LambdaFunctor <T>> (m_callable);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
Lambda () noexcept : Lambda (nullptr)
|
||||
explicit Lambda () noexcept : Lambda (nullptr)
|
||||
{ }
|
||||
|
||||
Lambda (decltype (nullptr)) noexcept : m_functor (nullptr), m_smallObject (false)
|
||||
|
|
@ -124,7 +124,7 @@ public:
|
|||
template <typename F> Lambda (F function) {
|
||||
if (cr::fix (sizeof (function) > LamdaSmallBufferLength)) {
|
||||
m_smallObject = false;
|
||||
new (m_small) UniquePtr <LambdaFunctorWrapper> (createUniqueBase <LambdaFunctor <F>, LambdaFunctorWrapper> (cr::move (function)));
|
||||
new (m_small) UniquePtr <LambdaFunctorWrapper> (makeUnique <LambdaFunctor <F>> (cr::move (function)));
|
||||
}
|
||||
else {
|
||||
m_smallObject = true;
|
||||
|
|
|
|||
|
|
@ -18,12 +18,8 @@
|
|||
# include <fcntl.h>
|
||||
# include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
#elif defined (CR_WINDOWS)
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// handling dynamic library loading
|
||||
|
|
@ -47,6 +43,10 @@ public:
|
|||
|
||||
public:
|
||||
bool load (const String &file) noexcept {
|
||||
if (*this) {
|
||||
unload ();
|
||||
}
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
m_handle = LoadLibraryA (file.chars ());
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -14,11 +14,6 @@
|
|||
#include <crlib/cr-files.h>
|
||||
#include <crlib/cr-lambda.h>
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
class SimpleLogger final : public Singleton <SimpleLogger> {
|
||||
|
|
|
|||
|
|
@ -70,6 +70,15 @@ CR_NAMESPACE_END
|
|||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# include <direct.h>
|
||||
|
||||
# if defined (max)
|
||||
# undef max
|
||||
# endif
|
||||
|
||||
# if defined (min)
|
||||
# undef min
|
||||
# endif
|
||||
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <strings.h>
|
||||
|
|
@ -77,8 +86,10 @@ CR_NAMESPACE_END
|
|||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined (CR_ANDROID)
|
||||
# include <android/log.h>
|
||||
|
|
@ -88,42 +99,42 @@ CR_NAMESPACE_BEGIN
|
|||
|
||||
// helper struct for platform detection
|
||||
struct Platform : public Singleton <Platform> {
|
||||
bool isWindows = false;
|
||||
bool isLinux = false;
|
||||
bool isOSX = false;
|
||||
bool isAndroid = false;
|
||||
bool isAndroidHardFP = false;
|
||||
bool isX64 = false;
|
||||
bool isArm = false;
|
||||
bool win32 = false;
|
||||
bool linux = false;
|
||||
bool osx = false;
|
||||
bool android = false;
|
||||
bool hfp = false;
|
||||
bool x64 = false;
|
||||
bool arm = false;
|
||||
|
||||
Platform () {
|
||||
#if defined(CR_WINDOWS)
|
||||
isWindows = true;
|
||||
win32 = true;
|
||||
#endif
|
||||
|
||||
#if defined(CR_ANDROID)
|
||||
isAndroid = true;
|
||||
android = true;
|
||||
|
||||
# if defined (CR_ANDROID_HARD_FP)
|
||||
isAndroidHardFP = true;
|
||||
hfp = true;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(CR_LINUX)
|
||||
isLinux = true;
|
||||
linux = true;
|
||||
#endif
|
||||
|
||||
#if defined(CR_OSX)
|
||||
isOSX = true;
|
||||
osx = true;
|
||||
#endif
|
||||
|
||||
#if defined(CR_ARCH_X64) || defined(CR_ARCH_ARM64)
|
||||
isX64 = true;
|
||||
x64 = true;
|
||||
#endif
|
||||
|
||||
#if defined(CR_ARCH_ARM)
|
||||
isArm = true;
|
||||
isAndroid = true;
|
||||
arm = true;
|
||||
android = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,38 @@
|
|||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
namespace detail {
|
||||
template <typename T> uint8 &getMostSignificantByte (T &object) {
|
||||
return *(reinterpret_cast <uint8 *> (&object) + sizeof (object) - 1);
|
||||
}
|
||||
|
||||
template <size_t N> bool getLeastSignificantBit (uint8 byte) {
|
||||
return byte & cr::bit (N);
|
||||
}
|
||||
|
||||
template <size_t N> bool getMostSignificantBit (uint8 byte) {
|
||||
return byte & cr::bit (CHAR_BIT - N - 1);
|
||||
}
|
||||
|
||||
template <size_t N> void setLeastSignificantBit (uint8 &byte, bool bit) {
|
||||
if (bit) {
|
||||
byte |= cr::bit (N);
|
||||
}
|
||||
else {
|
||||
byte &= ~cr::bit (N);
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t N> void setMostSignificantBit (uint8 &byte, bool bit) {
|
||||
if (bit) {
|
||||
byte |= cr::bit (CHAR_BIT - N - 1);
|
||||
}
|
||||
else {
|
||||
byte &= ~cr::bit (CHAR_BIT - N - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// small-string optimized string class, sso stuff based on: https://github.com/elliotgoodrich/SSO-23/
|
||||
class String final {
|
||||
public:
|
||||
|
|
@ -30,7 +62,6 @@ public:
|
|||
private:
|
||||
enum : size_t {
|
||||
ExcessSpace = 32,
|
||||
CharBit = CHAR_BIT
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -77,8 +108,7 @@ public:
|
|||
assign (ch);
|
||||
}
|
||||
|
||||
String (String &&rhs) noexcept {
|
||||
m_data = rhs.m_data;
|
||||
String (String &&rhs) noexcept : m_data (rhs.m_data) {
|
||||
rhs.setMoved ();
|
||||
}
|
||||
|
||||
|
|
@ -87,35 +117,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
template <typename T> static uint8 &getMostSignificantByte (T &object) {
|
||||
return *(reinterpret_cast <uint8 *> (&object) + sizeof (object) - 1);
|
||||
}
|
||||
|
||||
template <size_t N> static bool getLeastSignificantBit (uint8 byte) {
|
||||
return byte & cr::bit (N);
|
||||
}
|
||||
|
||||
template <size_t N> static bool getMostSignificantBit (uint8 byte) {
|
||||
return byte & cr::bit (CharBit - N - 1);
|
||||
}
|
||||
|
||||
template <size_t N> static void setLeastSignificantBit (uint8 &byte, bool bit) {
|
||||
if (bit) {
|
||||
byte |= cr::bit (N);
|
||||
}
|
||||
else {
|
||||
byte &= ~cr::bit (N);
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t N> static void setMostSignificantBit (uint8 &byte, bool bit) {
|
||||
if (bit) {
|
||||
byte |= cr::bit (CharBit - N - 1);
|
||||
}
|
||||
else {
|
||||
byte &= ~cr::bit (CharBit - N - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy () {
|
||||
if (!isSmall ()) {
|
||||
|
|
@ -162,7 +163,7 @@ private:
|
|||
}
|
||||
|
||||
bool isSmall () const {
|
||||
return !getLeastSignificantBit <0> (m_data.small.length) && !getLeastSignificantBit <1> (m_data.small.length);
|
||||
return !detail::getLeastSignificantBit <0> (m_data.small.length) && !detail::getLeastSignificantBit <1> (m_data.small.length);
|
||||
}
|
||||
|
||||
void setSmallLength (uint8 length) {
|
||||
|
|
@ -174,18 +175,18 @@ private:
|
|||
}
|
||||
|
||||
void setDataNonSmall (size_t length, size_t capacity) {
|
||||
uint8 &lengthHighByte = getMostSignificantByte (length);
|
||||
uint8 &capacityHighByte = getMostSignificantByte (capacity);
|
||||
uint8 &lengthHighByte = detail::getMostSignificantByte (length);
|
||||
uint8 &capacityHighByte = detail::getMostSignificantByte (capacity);
|
||||
|
||||
const bool lengthHasHighBit = getMostSignificantBit <0> (lengthHighByte);
|
||||
const bool capacityHasHighBit = getMostSignificantBit <0> (capacityHighByte);
|
||||
const bool capacityHasSecHighBit = getMostSignificantBit <1> (capacityHighByte);
|
||||
const bool lengthHasHighBit = detail::getMostSignificantBit <0> (lengthHighByte);
|
||||
const bool capacityHasHighBit = detail::getMostSignificantBit <0> (capacityHighByte);
|
||||
const bool capacityHasSecHighBit = detail::getMostSignificantBit <1> (capacityHighByte);
|
||||
|
||||
setMostSignificantBit <0> (lengthHighByte, capacityHasSecHighBit);
|
||||
detail::setMostSignificantBit <0> (lengthHighByte, capacityHasSecHighBit);
|
||||
|
||||
capacityHighByte <<= 2;
|
||||
setLeastSignificantBit <0> (capacityHighByte, capacityHasHighBit);
|
||||
setLeastSignificantBit <1> (capacityHighByte, !lengthHasHighBit);
|
||||
detail::setLeastSignificantBit <0> (capacityHighByte, capacityHasHighBit);
|
||||
detail::setLeastSignificantBit <1> (capacityHighByte, !lengthHasHighBit);
|
||||
|
||||
m_data.big.length = length;
|
||||
m_data.big.capacity = capacity;
|
||||
|
|
@ -195,18 +196,18 @@ private:
|
|||
size_t length = m_data.big.length;
|
||||
size_t capacity = m_data.big.capacity;
|
||||
|
||||
uint8 &lengthHighByte = getMostSignificantByte (length);
|
||||
uint8 &capacityHighByte = getMostSignificantByte (capacity);
|
||||
uint8 &lengthHighByte = detail::getMostSignificantByte (length);
|
||||
uint8 &capacityHighByte = detail::getMostSignificantByte (capacity);
|
||||
|
||||
const bool capacityHasHighBit = getLeastSignificantBit <0> (capacityHighByte);
|
||||
const bool lengthHasHighBit = !getLeastSignificantBit <1> (capacityHighByte);
|
||||
const bool capacityHasSecHighBit = getMostSignificantBit <0> (lengthHighByte);
|
||||
const bool capacityHasHighBit = detail::getLeastSignificantBit <0> (capacityHighByte);
|
||||
const bool lengthHasHighBit = !detail::getLeastSignificantBit <1> (capacityHighByte);
|
||||
const bool capacityHasSecHighBit = detail::getMostSignificantBit <0> (lengthHighByte);
|
||||
|
||||
setMostSignificantBit <0> (lengthHighByte, lengthHasHighBit);
|
||||
detail::setMostSignificantBit <0> (lengthHighByte, lengthHasHighBit);
|
||||
|
||||
capacityHighByte >>= 2;
|
||||
setMostSignificantBit <0> (capacityHighByte, capacityHasHighBit);
|
||||
setMostSignificantBit <1> (capacityHighByte, capacityHasSecHighBit);
|
||||
detail::setMostSignificantBit <0> (capacityHighByte, capacityHasHighBit);
|
||||
detail::setMostSignificantBit <1> (capacityHighByte, capacityHasSecHighBit);
|
||||
|
||||
return { length, capacity };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple pair (twin)
|
||||
template <typename A, typename B> class Twin {
|
||||
template <typename A, typename B> class Twin final {
|
||||
public:
|
||||
A first;
|
||||
B second;
|
||||
|
|
@ -55,13 +55,4 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// creating pairs
|
||||
template <typename A, typename B> constexpr Twin <A, B> makeTwin (A &&a, B &&b) {
|
||||
return Twin <A, B> (cr::forward <A> (a), cr::forward <B> (b));
|
||||
}
|
||||
|
||||
template <typename A, typename B> constexpr Twin <A, B> makeTwin (const A &a, const B &b) {
|
||||
return Twin <A, B> (a, b);
|
||||
}
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -41,10 +41,11 @@ private:
|
|||
SmallArray <int32> m_prevTable;
|
||||
|
||||
public:
|
||||
ULZ () {
|
||||
explicit ULZ () {
|
||||
m_hashTable.resize (HashLength);
|
||||
m_prevTable.resize (WindowSize);
|
||||
}
|
||||
|
||||
~ULZ () = default;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -21,12 +21,15 @@ private:
|
|||
|
||||
public:
|
||||
UniquePtr () = default;
|
||||
|
||||
explicit UniquePtr (T *ptr) : m_ptr (ptr)
|
||||
{ }
|
||||
|
||||
UniquePtr (UniquePtr &&rhs) noexcept : m_ptr (rhs.m_ptr) {
|
||||
rhs.m_ptr = nullptr;
|
||||
}
|
||||
UniquePtr (UniquePtr &&rhs) noexcept : m_ptr (rhs.release ())
|
||||
{ }
|
||||
|
||||
template <typename U> UniquePtr (UniquePtr <U> &&rhs) noexcept : m_ptr (rhs.release ())
|
||||
{ }
|
||||
|
||||
~UniquePtr () {
|
||||
destroy ();
|
||||
|
|
@ -60,10 +63,14 @@ private:
|
|||
public:
|
||||
UniquePtr &operator = (UniquePtr &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
destroy ();
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
m_ptr = rhs.m_ptr;
|
||||
rhs.m_ptr = nullptr;
|
||||
template <typename U> UniquePtr &operator = (UniquePtr <U> &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -87,13 +94,8 @@ public:
|
|||
};
|
||||
|
||||
// create unique
|
||||
template <typename T, typename... Args> UniquePtr <T> createUnique (Args &&... args) {
|
||||
template <typename T, typename... Args> UniquePtr <T> makeUnique (Args &&... args) {
|
||||
return UniquePtr <T> (alloc.create <T> (cr::forward <Args> (args)...));
|
||||
}
|
||||
|
||||
// create unique (base class)
|
||||
template <typename D, typename B, typename... Args> UniquePtr <B> createUniqueBase (Args &&... args) {
|
||||
return UniquePtr <B> (alloc.create <D> (cr::forward <Args> (args)...));
|
||||
}
|
||||
|
||||
CR_NAMESPACE_END
|
||||
Loading…
Add table
Add a link
Reference in a new issue