[add] first
This commit is contained in:
34
Libraries/libil2cpp/include/utils/BaselibHandleUtils.h
Normal file
34
Libraries/libil2cpp/include/utils/BaselibHandleUtils.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class BaselibHandleUtils
|
||||
{
|
||||
public:
|
||||
template<typename BaselibHandleType>
|
||||
static void* HandleToVoidPtr(BaselibHandleType baselibHandle)
|
||||
{
|
||||
// following asserts check that the handle fits into void* in its entirety
|
||||
static_assert(sizeof(BaselibHandleType) <= sizeof(void*), "baselib handle does not fit void*");
|
||||
static_assert(sizeof(BaselibHandleType::handle) <= sizeof(void*), "baselib handle does not fit void*");
|
||||
void* result = nullptr;
|
||||
memcpy(&result, &baselibHandle.handle, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename BaselibHandleType>
|
||||
static BaselibHandleType VoidPtrToHandle(void* ptr)
|
||||
{
|
||||
static_assert(sizeof(BaselibHandleType) <= sizeof(void*), "baselib handle does not fit void*");
|
||||
static_assert(sizeof(BaselibHandleType::handle) <= sizeof(void*), "baselib handle does not fit void*");
|
||||
decltype(BaselibHandleType::handle)result = {};
|
||||
memcpy(&result, &ptr, sizeof(ptr));
|
||||
return BaselibHandleType { result };
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
47
Libraries/libil2cpp/include/utils/CallOnce.h
Normal file
47
Libraries/libil2cpp/include/utils/CallOnce.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "NonCopyable.h"
|
||||
#include "../os/Mutex.h"
|
||||
|
||||
#include "Baselib.h"
|
||||
#include "Cpp/Atomic.h"
|
||||
#include "Cpp/ReentrantLock.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
typedef void (*CallOnceFunc) (void* arg);
|
||||
|
||||
struct OnceFlag : NonCopyable
|
||||
{
|
||||
OnceFlag() : m_IsSet(false)
|
||||
{
|
||||
}
|
||||
|
||||
friend void CallOnce(OnceFlag& flag, CallOnceFunc func, void* arg);
|
||||
|
||||
bool IsSet()
|
||||
{
|
||||
return m_IsSet;
|
||||
}
|
||||
|
||||
private:
|
||||
baselib::atomic<bool> m_IsSet;
|
||||
baselib::ReentrantLock m_Mutex;
|
||||
};
|
||||
|
||||
inline void CallOnce(OnceFlag& flag, CallOnceFunc func, void* arg)
|
||||
{
|
||||
if (!flag.m_IsSet)
|
||||
{
|
||||
os::FastAutoLock lock(&flag.m_Mutex);
|
||||
if (!flag.m_IsSet)
|
||||
{
|
||||
func(arg);
|
||||
flag.m_IsSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
256
Libraries/libil2cpp/include/utils/Collections.h
Normal file
256
Libraries/libil2cpp/include/utils/Collections.h
Normal file
@@ -0,0 +1,256 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include "NonCopyable.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
namespace collections
|
||||
{
|
||||
// Memory compact, map-like data structure that stores values and
|
||||
// is a able to compute the key from the value with the provided converter
|
||||
// This data structure is perfect to storing values that will not be changed
|
||||
// for the duration of program (like type metadata) and need fast querying
|
||||
//
|
||||
// It is able to store multiple values associated with a single key, and query them through find()
|
||||
// find_first() is a special case find() which improves performance for cases where we don't store multiple values for each key
|
||||
template<typename TKey, typename TValue, typename TValueToKeyConverter, typename TKeyLess = std::less<TKey>, typename TKeyEquals = std::equal_to<TKey> >
|
||||
class ArrayValueMap : NonCopyable
|
||||
{
|
||||
public:
|
||||
typedef ArrayValueMap<TKey, TValue, TValueToKeyConverter, TKeyLess, TKeyEquals> map_type;
|
||||
typedef const TValue* iterator;
|
||||
|
||||
private:
|
||||
const TValue* m_Values;
|
||||
const size_t m_ValueCount;
|
||||
bool m_OwnStorage;
|
||||
const TValueToKeyConverter m_ValueToKeyConverter;
|
||||
const TKeyLess m_KeyLessComparer;
|
||||
const TKeyEquals m_KeyEqualsComparer;
|
||||
|
||||
struct SortComparer
|
||||
{
|
||||
private:
|
||||
const TValueToKeyConverter m_ValueToKeyConverter;
|
||||
const TKeyLess m_KeyComparer;
|
||||
|
||||
public:
|
||||
SortComparer(TValueToKeyConverter valueToKeyConverter, TKeyLess keyComparer) :
|
||||
m_ValueToKeyConverter(valueToKeyConverter), m_KeyComparer(keyComparer)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool operator()(const TValue& left, const TValue& right) const
|
||||
{
|
||||
return m_KeyComparer(m_ValueToKeyConverter(left), m_ValueToKeyConverter(right));
|
||||
}
|
||||
};
|
||||
|
||||
struct LowerBoundFindComparer
|
||||
{
|
||||
private:
|
||||
const TValueToKeyConverter m_ValueToKeyConverter;
|
||||
const TKeyLess m_KeyComparer;
|
||||
|
||||
public:
|
||||
LowerBoundFindComparer(TValueToKeyConverter valueToKeyConverter, TKeyLess keyComparer) :
|
||||
m_ValueToKeyConverter(valueToKeyConverter), m_KeyComparer(keyComparer)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool operator()(const TValue& left, const TKey& right) const
|
||||
{
|
||||
return m_KeyComparer(m_ValueToKeyConverter(left), right);
|
||||
}
|
||||
};
|
||||
|
||||
struct UpperBoundFindComparer
|
||||
{
|
||||
private:
|
||||
const TValueToKeyConverter m_ValueToKeyConverter;
|
||||
const TKeyLess m_KeyComparer;
|
||||
|
||||
public:
|
||||
UpperBoundFindComparer(TValueToKeyConverter valueToKeyConverter, TKeyLess keyComparer) :
|
||||
m_ValueToKeyConverter(valueToKeyConverter), m_KeyComparer(keyComparer)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool operator()(const TKey& left, const TValue& right) const
|
||||
{
|
||||
return m_KeyComparer(left, m_ValueToKeyConverter(right));
|
||||
}
|
||||
};
|
||||
|
||||
inline static TValue* InitializeInPlace(TValue* values, size_t valueCount, TValueToKeyConverter valueToKeyConverter, TKeyLess keyLessComparer)
|
||||
{
|
||||
std::sort(values, values + valueCount, SortComparer(valueToKeyConverter, keyLessComparer));
|
||||
return values;
|
||||
}
|
||||
|
||||
inline static TValue* AllocateAndInitialize(const TValue* originalValues, size_t valueCount, TValueToKeyConverter valueToKeyConverter, TKeyLess keyLessComparer)
|
||||
{
|
||||
TValue* values = new TValue[valueCount];
|
||||
memcpy(values, originalValues, valueCount * sizeof(TValue));
|
||||
|
||||
return InitializeInPlace(values, valueCount, valueToKeyConverter, keyLessComparer);
|
||||
}
|
||||
|
||||
public:
|
||||
inline ArrayValueMap() :
|
||||
m_Values(NULL),
|
||||
m_ValueCount(0),
|
||||
m_OwnStorage(false),
|
||||
m_ValueToKeyConverter(TValueToKeyConverter()),
|
||||
m_KeyLessComparer(TKeyLess()),
|
||||
m_KeyEqualsComparer(TKeyEquals())
|
||||
{
|
||||
}
|
||||
|
||||
// Non-allocating constructor. It will take a pointer and will not allocate any storage
|
||||
// It WILL sort existing values
|
||||
inline ArrayValueMap(TValue* values, size_t valueCount, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(),
|
||||
TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals()) :
|
||||
m_Values(InitializeInPlace(values, valueCount, valueToKeyConverter, keyLessComparer)),
|
||||
m_ValueCount(valueCount),
|
||||
m_ValueToKeyConverter(valueToKeyConverter),
|
||||
m_KeyLessComparer(keyLessComparer),
|
||||
m_KeyEqualsComparer(keyEqualsComparer),
|
||||
m_OwnStorage(false)
|
||||
{
|
||||
}
|
||||
|
||||
// Allocating constructor
|
||||
// Will copy values to newly allocated storage
|
||||
inline ArrayValueMap(const std::vector<TValue>& values, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(),
|
||||
TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals()) :
|
||||
m_Values(AllocateAndInitialize(values.data(), values.size(), valueToKeyConverter, keyLessComparer)),
|
||||
m_ValueCount(values.size()),
|
||||
m_ValueToKeyConverter(valueToKeyConverter),
|
||||
m_KeyLessComparer(keyLessComparer),
|
||||
m_KeyEqualsComparer(keyEqualsComparer),
|
||||
m_OwnStorage(true)
|
||||
{
|
||||
}
|
||||
|
||||
~ArrayValueMap()
|
||||
{
|
||||
if (m_OwnStorage)
|
||||
{
|
||||
delete[] m_Values;
|
||||
}
|
||||
}
|
||||
|
||||
inline void assign_external(TValue* values, size_t valueCount, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(),
|
||||
TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals())
|
||||
{
|
||||
this->~ArrayValueMap();
|
||||
new(this) map_type(values, valueCount, valueToKeyConverter, keyLessComparer, keyEqualsComparer);
|
||||
}
|
||||
|
||||
// Constructs map that contains pointers to original array
|
||||
inline void assign_addresses(const TValue& valueArray, size_t valueCount, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(),
|
||||
TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals())
|
||||
{
|
||||
this->~ArrayValueMap();
|
||||
|
||||
TValue* storage = NULL;
|
||||
|
||||
if (valueCount > 0)
|
||||
{
|
||||
storage = new TValue[valueCount];
|
||||
|
||||
for (size_t i = 0; i < valueCount; i++)
|
||||
{
|
||||
storage[i] = &valueArray[i];
|
||||
}
|
||||
}
|
||||
|
||||
new(this) map_type(storage, valueCount, valueToKeyConverter, keyLessComparer, keyEqualsComparer);
|
||||
m_OwnStorage = true;
|
||||
}
|
||||
|
||||
inline void assign(const std::vector<TValue>& values, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(),
|
||||
TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals())
|
||||
{
|
||||
this->~ArrayValueMap();
|
||||
new(this) map_type(values, valueToKeyConverter, keyLessComparer, keyEqualsComparer);
|
||||
}
|
||||
|
||||
inline iterator begin() const
|
||||
{
|
||||
return m_Values;
|
||||
}
|
||||
|
||||
inline iterator end() const
|
||||
{
|
||||
return m_Values + m_ValueCount;
|
||||
}
|
||||
|
||||
template<typename EqualsPredicate>
|
||||
inline iterator find(const TKey& key, const EqualsPredicate& equalsPredicate) const
|
||||
{
|
||||
iterator dataStart = begin();
|
||||
iterator dataEnd = end();
|
||||
iterator ptr = std::lower_bound(dataStart, dataEnd, key, LowerBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer));
|
||||
|
||||
for (; ptr != dataEnd && m_KeyEqualsComparer(m_ValueToKeyConverter(*ptr), key); ptr++)
|
||||
{
|
||||
if (equalsPredicate(*ptr))
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return dataEnd;
|
||||
}
|
||||
|
||||
inline iterator find_first(const TKey& key) const
|
||||
{
|
||||
iterator dataStart = begin();
|
||||
iterator dataEnd = end();
|
||||
iterator ptr = std::lower_bound(dataStart, dataEnd, key, LowerBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer));
|
||||
|
||||
if (ptr != dataEnd && m_KeyEqualsComparer(m_ValueToKeyConverter(*ptr), key))
|
||||
return ptr;
|
||||
|
||||
return dataEnd;
|
||||
}
|
||||
|
||||
inline iterator lower_bound(const TKey& key) const
|
||||
{
|
||||
return std::lower_bound(begin(), end(), key, LowerBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer));
|
||||
}
|
||||
|
||||
inline iterator upper_bound(const TKey& key) const
|
||||
{
|
||||
return std::upper_bound(begin(), end(), key, UpperBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer));
|
||||
}
|
||||
|
||||
inline size_t size() const
|
||||
{
|
||||
return m_ValueCount;
|
||||
}
|
||||
|
||||
inline const TValue& operator[](size_t i) const
|
||||
{
|
||||
return m_Values[i];
|
||||
}
|
||||
|
||||
template<typename Mutator>
|
||||
inline void mutate(Mutator& mutator)
|
||||
{
|
||||
size_t count = m_ValueCount;
|
||||
const TValue* values = m_Values;
|
||||
for (size_t i = 0; i < count; i++)
|
||||
mutator(const_cast<TValue*>(values + i));
|
||||
|
||||
m_Values = InitializeInPlace(const_cast<TValue*>(values), count, m_ValueToKeyConverter, m_KeyLessComparer);
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace utils
|
||||
} // namespace il2cpp
|
||||
13
Libraries/libil2cpp/include/utils/DirectoryUtils.h
Normal file
13
Libraries/libil2cpp/include/utils/DirectoryUtils.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
bool Match(const std::string name, size_t nameIndex, const std::string& pattern, const size_t patternIndex);
|
||||
bool Match(const std::string name, const std::string& pattern);
|
||||
std::string CollapseAdjacentStars(const std::string& pattern);
|
||||
}
|
||||
}
|
||||
22
Libraries/libil2cpp/include/utils/Environment.h
Normal file
22
Libraries/libil2cpp/include/utils/Environment.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include "il2cpp-config.h"
|
||||
#include "il2cpp-string-types.h"
|
||||
struct Il2CppDomain;
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class LIBIL2CPP_CODEGEN_API Environment
|
||||
{
|
||||
public:
|
||||
static const std::vector<UTF16String>& GetMainArgs();
|
||||
static int GetNumMainArgs();
|
||||
static void SetMainArgs(const char* const* args, int num_args);
|
||||
static void SetMainArgs(const Il2CppChar* const* args, int num_args);
|
||||
};
|
||||
} /* namespace vm */
|
||||
} /* namespace il2cpp */
|
||||
22
Libraries/libil2cpp/include/utils/Exception.h
Normal file
22
Libraries/libil2cpp/include/utils/Exception.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "il2cpp-config.h"
|
||||
#include <string>
|
||||
struct Il2CppException;
|
||||
|
||||
#include "Baselib.h"
|
||||
#include "C/Baselib_ErrorState.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class LIBIL2CPP_CODEGEN_API Exception
|
||||
{
|
||||
public:
|
||||
static std::string FormatException(const Il2CppException* ex);
|
||||
static std::string FormatStackTrace(const Il2CppException* ex);
|
||||
static std::string FormatInvalidCastException(const Il2CppClass* fromType, const Il2CppClass* toType);
|
||||
static std::string FormatBaselibErrorState(const Baselib_ErrorState& errorState);
|
||||
};
|
||||
} // utils
|
||||
} // utils
|
||||
50
Libraries/libil2cpp/include/utils/ExceptionSupportStack.h
Normal file
50
Libraries/libil2cpp/include/utils/ExceptionSupportStack.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
template<typename T, int Size>
|
||||
class ExceptionSupportStack
|
||||
{
|
||||
public:
|
||||
ExceptionSupportStack() : m_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
void push(T value)
|
||||
{
|
||||
// This function is rather unsafe. We don't track the size of storage,
|
||||
// and assume the caller will not push more values than it has allocated.
|
||||
// This function should only be used from generated code, where
|
||||
// we control the calls to this function.
|
||||
IL2CPP_ASSERT(m_count < Size);
|
||||
m_Storage[m_count] = value;
|
||||
m_count++;
|
||||
}
|
||||
|
||||
void pop()
|
||||
{
|
||||
IL2CPP_ASSERT(!empty());
|
||||
m_count--;
|
||||
}
|
||||
|
||||
T top() const
|
||||
{
|
||||
IL2CPP_ASSERT(!empty());
|
||||
return m_Storage[m_count - 1];
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_count == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_Storage[Size];
|
||||
int m_count;
|
||||
};
|
||||
}
|
||||
}
|
||||
46
Libraries/libil2cpp/include/utils/Expected.h
Normal file
46
Libraries/libil2cpp/include/utils/Expected.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
#include "utils/Il2CppError.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
template<typename T>
|
||||
class Expected
|
||||
{
|
||||
public:
|
||||
Expected(const T& result) : m_Result(result) {}
|
||||
Expected(const Il2CppError& error) : m_Error(error) {}
|
||||
|
||||
bool HasError() const
|
||||
{
|
||||
return m_Error.GetErrorCode() != NoError;
|
||||
}
|
||||
|
||||
Il2CppError GetError() const
|
||||
{
|
||||
return m_Error;
|
||||
}
|
||||
|
||||
T& Get()
|
||||
{
|
||||
IL2CPP_ASSERT(!HasError());
|
||||
return m_Result;
|
||||
}
|
||||
|
||||
const T& Get() const
|
||||
{
|
||||
IL2CPP_ASSERT(!HasError());
|
||||
return m_Result;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_Result;
|
||||
const Il2CppError m_Error;
|
||||
|
||||
Expected() {}
|
||||
};
|
||||
} // namespace il2cpp
|
||||
} // namespace utils
|
||||
98
Libraries/libil2cpp/include/utils/ExtendedAtomicTypes.h
Normal file
98
Libraries/libil2cpp/include/utils/ExtendedAtomicTypes.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
|
||||
# include <emmintrin.h>
|
||||
|
||||
/// atomic_word must be 8 bytes aligned if you want to use it with atomic_* ops.
|
||||
# if defined(_MSC_VER)
|
||||
typedef __int64 atomic_word;
|
||||
# else
|
||||
typedef long long atomic_word;
|
||||
# endif
|
||||
|
||||
/// atomic_word2 must be 16 bytes aligned if you want to use it with atomic_* ops.
|
||||
union atomic_word2
|
||||
{
|
||||
__m128i v;
|
||||
struct
|
||||
{
|
||||
atomic_word lo, hi;
|
||||
};
|
||||
};
|
||||
|
||||
#define IL2CPP_ATOMIC_HAS_QUEUE
|
||||
|
||||
#elif defined(__x86__) || defined(__i386__) || defined(_M_IX86)
|
||||
|
||||
/// atomic_word must be 4 bytes aligned if you want to use it with atomic_* ops.
|
||||
typedef int atomic_word;
|
||||
|
||||
/// atomic_word2 must be 8 bytes aligned if you want to use it with atomic_* ops.
|
||||
union atomic_word2
|
||||
{
|
||||
# if defined(_MSC_VER)
|
||||
__int64 v;
|
||||
# else
|
||||
long long v;
|
||||
# endif
|
||||
# if !defined(__SSE2__)
|
||||
double d;
|
||||
# endif
|
||||
struct
|
||||
{
|
||||
atomic_word lo, hi;
|
||||
};
|
||||
};
|
||||
|
||||
#define IL2CPP_ATOMIC_HAS_QUEUE
|
||||
|
||||
#elif defined(_M_ARM64) || (defined(__arm64__) || defined(__aarch64__)) && (defined(__clang__) || defined(__GNUC__))
|
||||
|
||||
typedef long long atomic_word;
|
||||
struct alignas(16) atomic_word2
|
||||
{
|
||||
atomic_word lo;
|
||||
atomic_word hi;
|
||||
};
|
||||
|
||||
#define IL2CPP_ATOMIC_HAS_QUEUE
|
||||
|
||||
#elif defined(_M_ARM) || (defined(__arm__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)) && (defined(__clang__) || defined(__GNUC__)))
|
||||
|
||||
typedef int atomic_word;
|
||||
union atomic_word2
|
||||
{
|
||||
# if defined(_MSC_VER)
|
||||
__int64 v;
|
||||
# else
|
||||
long long v;
|
||||
# endif
|
||||
struct
|
||||
{
|
||||
atomic_word lo;
|
||||
atomic_word hi;
|
||||
};
|
||||
};
|
||||
|
||||
#define IL2CPP_ATOMIC_HAS_QUEUE
|
||||
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
|
||||
#include <stdint.h>
|
||||
typedef int32_t atomic_word;
|
||||
union atomic_word2
|
||||
{
|
||||
int64_t v;
|
||||
struct
|
||||
{
|
||||
atomic_word lo;
|
||||
atomic_word hi;
|
||||
};
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#error There is no atomic_word implementation for this platform.
|
||||
|
||||
#endif
|
||||
41
Libraries/libil2cpp/include/utils/Functional.h
Normal file
41
Libraries/libil2cpp/include/utils/Functional.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/NonCopyable.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
namespace functional
|
||||
{
|
||||
struct TrueFilter
|
||||
{
|
||||
template<typename T>
|
||||
inline bool operator()(const T& item) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ItemType, typename Comparer>
|
||||
struct Filter : NonCopyable
|
||||
{
|
||||
private:
|
||||
ItemType m_Item;
|
||||
Comparer m_Comparer;
|
||||
|
||||
public:
|
||||
Filter(ItemType item, Comparer comparer = Comparer()) :
|
||||
m_Item(item), m_Comparer(comparer)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool operator()(const T& item) const
|
||||
{
|
||||
return m_Comparer(m_Item, item);
|
||||
}
|
||||
};
|
||||
} // functional
|
||||
} // utils
|
||||
} // il2cpp
|
||||
40
Libraries/libil2cpp/include/utils/HashUtils.h
Normal file
40
Libraries/libil2cpp/include/utils/HashUtils.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class HashUtils
|
||||
{
|
||||
static const size_t Seed = 486187739;
|
||||
public:
|
||||
static inline size_t Combine(size_t hash1, size_t hash2)
|
||||
{
|
||||
return hash1 * Seed + hash2;
|
||||
}
|
||||
|
||||
static inline size_t AlignedPointerHash(const void* ptr)
|
||||
{
|
||||
return ((uintptr_t)ptr) >> 3;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct PointerHash
|
||||
{
|
||||
size_t operator()(const T* value) const
|
||||
{
|
||||
return (size_t)value;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct PassThroughHash
|
||||
{
|
||||
size_t operator()(T value) const
|
||||
{
|
||||
return (size_t)value;
|
||||
}
|
||||
};
|
||||
} /* namespace vm */
|
||||
} /* namespace il2cpp */
|
||||
35
Libraries/libil2cpp/include/utils/Il2CppError.h
Normal file
35
Libraries/libil2cpp/include/utils/Il2CppError.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "il2cpp-config.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
enum Il2CppErrorCode
|
||||
{
|
||||
NoError,
|
||||
NotSupported,
|
||||
ComError,
|
||||
UnauthorizedAccess,
|
||||
};
|
||||
|
||||
class Il2CppError
|
||||
{
|
||||
public:
|
||||
Il2CppError();
|
||||
Il2CppError(Il2CppErrorCode errorCode, const char* message);
|
||||
Il2CppError(Il2CppErrorCode errorCode, il2cpp_hresult_t hr);
|
||||
Il2CppErrorCode GetErrorCode() const;
|
||||
std::string GetErrorMessage() const;
|
||||
il2cpp_hresult_t GetHr() const;
|
||||
bool GetDefaultToCOMException() const;
|
||||
|
||||
private:
|
||||
const Il2CppErrorCode m_ErrorCode;
|
||||
const std::string m_Message;
|
||||
const il2cpp_hresult_t m_Hr;
|
||||
};
|
||||
} // namespace utils
|
||||
} // namespace error
|
||||
135
Libraries/libil2cpp/include/utils/Il2CppHashMap.h
Normal file
135
Libraries/libil2cpp/include/utils/Il2CppHashMap.h
Normal file
@@ -0,0 +1,135 @@
|
||||
#pragma once
|
||||
|
||||
// Mono code also has define for GROUP_SIZE, so we need to wrap its usage here
|
||||
#pragma push_macro("GROUP_SIZE")
|
||||
#undef GROUP_SIZE
|
||||
#if IL2CPP_USE_SPARSEHASH
|
||||
#include "../../external/google/sparsehash/sparse_hash_map.h"
|
||||
#else
|
||||
#include "../../external/google/sparsehash/dense_hash_map.h"
|
||||
#endif
|
||||
#pragma pop_macro("GROUP_SIZE")
|
||||
|
||||
#include "KeyWrapper.h"
|
||||
|
||||
#include "os/FastReaderReaderWriterLock.h"
|
||||
|
||||
template<class Key, class T,
|
||||
class HashFcn = SPARSEHASH_HASH<Key>,
|
||||
class EqualKey = std::equal_to<Key>,
|
||||
class Alloc = GOOGLE_NAMESPACE::libc_allocator_with_realloc<std::pair<const KeyWrapper<Key>, T> > >
|
||||
#if IL2CPP_USE_SPARSEHASH
|
||||
class Il2CppHashMap : public GOOGLE_NAMESPACE::sparse_hash_map<KeyWrapper<Key>, T, HashFcn, typename KeyWrapper<Key>::template EqualsComparer<EqualKey>, Alloc>
|
||||
#else
|
||||
class Il2CppHashMap : public GOOGLE_NAMESPACE::dense_hash_map<KeyWrapper<Key>, T, HashFcn, typename KeyWrapper<Key>::template EqualsComparer<EqualKey>, Alloc>
|
||||
#endif
|
||||
{
|
||||
private:
|
||||
#if IL2CPP_USE_SPARSEHASH
|
||||
typedef GOOGLE_NAMESPACE::sparse_hash_map<KeyWrapper<Key>, T, HashFcn, typename KeyWrapper<Key>::template EqualsComparer<EqualKey>, Alloc> Base;
|
||||
#else
|
||||
typedef GOOGLE_NAMESPACE::dense_hash_map<KeyWrapper<Key>, T, HashFcn, typename KeyWrapper<Key>::template EqualsComparer<EqualKey>, Alloc> Base;
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef typename Base::size_type size_type;
|
||||
typedef typename Base::hasher hasher;
|
||||
typedef typename Base::key_equal key_equal;
|
||||
typedef typename Base::key_type key_type;
|
||||
|
||||
explicit Il2CppHashMap(size_type n = 0,
|
||||
const hasher& hf = hasher(),
|
||||
const EqualKey& eql = EqualKey()) :
|
||||
Base(n, hf, key_equal(eql))
|
||||
{
|
||||
Base::set_deleted_key(key_type(key_type::KeyType_Deleted));
|
||||
#if !IL2CPP_USE_SPARSEHASH
|
||||
Base::set_empty_key(key_type(key_type::KeyType_Empty));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class InputIterator>
|
||||
Il2CppHashMap(InputIterator f, InputIterator l,
|
||||
size_type n = 0,
|
||||
const hasher& hf = hasher(),
|
||||
const EqualKey& eql = EqualKey()) :
|
||||
Base(f, l, n, hf, key_equal(eql))
|
||||
{
|
||||
Base::set_deleted_key(key_type(key_type::KeyType_Deleted));
|
||||
#if !IL2CPP_USE_SPARSEHASH
|
||||
Base::set_empty_key(key_type(key_type::KeyType_Empty));
|
||||
#endif
|
||||
}
|
||||
|
||||
void add(const key_type& key, const T& value)
|
||||
{
|
||||
Base::insert(std::make_pair(key, value));
|
||||
}
|
||||
};
|
||||
|
||||
template<class Key, class T,
|
||||
class HashFcn = SPARSEHASH_HASH<Key>,
|
||||
class EqualKey = std::equal_to<Key>,
|
||||
class Alloc = GOOGLE_NAMESPACE::libc_allocator_with_realloc<std::pair<const KeyWrapper<Key>, T> > >
|
||||
class Il2CppReaderWriterLockedHashMap
|
||||
{
|
||||
public:
|
||||
typedef typename Il2CppHashMap<Key, T, HashFcn, EqualKey, Alloc>::key_type key_type;
|
||||
typedef typename Il2CppHashMap<Key, T, HashFcn, EqualKey, Alloc>::size_type size_type;
|
||||
typedef typename Il2CppHashMap<Key, T, HashFcn, EqualKey, Alloc>::const_iterator const_iterator;
|
||||
typedef typename Il2CppHashMap<Key, T, HashFcn, EqualKey, Alloc>::iterator iterator;
|
||||
typedef typename Il2CppHashMap<Key, T, HashFcn, EqualKey, Alloc>::hasher hasher;
|
||||
|
||||
explicit Il2CppReaderWriterLockedHashMap(size_type n = 0,
|
||||
const hasher& hf = hasher(),
|
||||
const EqualKey& eql = EqualKey()) :
|
||||
hashMap(n, hf, eql)
|
||||
{
|
||||
}
|
||||
|
||||
bool TryGet(const key_type& key, T* value)
|
||||
{
|
||||
il2cpp::os::FastReaderReaderWriterAutoSharedLock readerLock(&lock);
|
||||
const_iterator iter = hashMap.find(key);
|
||||
if (iter != hashMap.end())
|
||||
{
|
||||
*value = iter->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Add(const key_type& key, const T& value)
|
||||
{
|
||||
il2cpp::os::FastReaderReaderWriterAutoExclusiveLock writerLock(&lock);
|
||||
return hashMap.insert(std::make_pair(key, value)).second;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
il2cpp::os::FastReaderReaderWriterAutoExclusiveLock writerLock(&lock);
|
||||
hashMap.clear();
|
||||
}
|
||||
|
||||
void Remove(const key_type& key)
|
||||
{
|
||||
il2cpp::os::FastReaderReaderWriterAutoExclusiveLock readerLock(&lock);
|
||||
hashMap.erase(key);
|
||||
}
|
||||
|
||||
// This function takes no locks, some other lock must be used to protect accesses
|
||||
iterator UnlockedBegin()
|
||||
{
|
||||
return hashMap.begin();
|
||||
}
|
||||
|
||||
// This function takes no locks, some other lock must be used to protect accesses
|
||||
iterator UnlockedEnd()
|
||||
{
|
||||
return hashMap.end();
|
||||
}
|
||||
|
||||
private:
|
||||
il2cpp::os::FastReaderReaderWriterLock lock;
|
||||
Il2CppHashMap<Key, T, HashFcn, EqualKey, Alloc> hashMap;
|
||||
};
|
||||
126
Libraries/libil2cpp/include/utils/Il2CppHashSet.h
Normal file
126
Libraries/libil2cpp/include/utils/Il2CppHashSet.h
Normal file
@@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
|
||||
// Mono code also has define for GROUP_SIZE, so we need to wrap its usage here
|
||||
#pragma push_macro("GROUP_SIZE")
|
||||
#undef GROUP_SIZE
|
||||
#if IL2CPP_USE_SPARSEHASH
|
||||
#include "../../external/google/sparsehash/sparse_hash_set.h"
|
||||
#else
|
||||
#include "../../external/google/sparsehash/dense_hash_set.h"
|
||||
#endif
|
||||
#pragma pop_macro("GROUP_SIZE")
|
||||
|
||||
#include "KeyWrapper.h"
|
||||
#include "os/FastReaderReaderWriterLock.h"
|
||||
|
||||
template<class Value,
|
||||
class HashFcn = SPARSEHASH_HASH<Value>,
|
||||
class EqualKey = std::equal_to<Value>,
|
||||
class Alloc = GOOGLE_NAMESPACE::libc_allocator_with_realloc<KeyWrapper<Value> > >
|
||||
#if IL2CPP_USE_SPARSEHASH
|
||||
class Il2CppHashSet : public GOOGLE_NAMESPACE::sparse_hash_set<KeyWrapper<Value>, HashFcn, typename KeyWrapper<Value>::template EqualsComparer<EqualKey>, Alloc>
|
||||
#else
|
||||
class Il2CppHashSet : public GOOGLE_NAMESPACE::dense_hash_set<KeyWrapper<Value>, HashFcn, typename KeyWrapper<Value>::template EqualsComparer<EqualKey>, Alloc>
|
||||
#endif
|
||||
{
|
||||
private:
|
||||
#if IL2CPP_USE_SPARSEHASH
|
||||
typedef GOOGLE_NAMESPACE::sparse_hash_set<KeyWrapper<Value>, HashFcn, typename KeyWrapper<Value>::template EqualsComparer<EqualKey>, Alloc> Base;
|
||||
#else
|
||||
typedef GOOGLE_NAMESPACE::dense_hash_set<KeyWrapper<Value>, HashFcn, typename KeyWrapper<Value>::template EqualsComparer<EqualKey>, Alloc> Base;
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef typename Base::size_type size_type;
|
||||
typedef typename Base::hasher hasher;
|
||||
typedef typename Base::key_equal key_equal;
|
||||
typedef typename Base::key_type key_type;
|
||||
|
||||
explicit Il2CppHashSet(size_type n = 0,
|
||||
const hasher& hf = hasher(),
|
||||
const EqualKey& eql = EqualKey()) :
|
||||
Base(n, hf, key_equal(eql))
|
||||
{
|
||||
Base::set_deleted_key(key_type(key_type::KeyType_Deleted));
|
||||
#if !IL2CPP_USE_SPARSEHASH
|
||||
Base::set_empty_key(key_type(key_type::KeyType_Empty));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class InputIterator>
|
||||
Il2CppHashSet(InputIterator f, InputIterator l,
|
||||
size_type n = 0,
|
||||
const hasher& hf = hasher(),
|
||||
const EqualKey& eql = EqualKey()) :
|
||||
Base(f, l, n, hf, key_equal(eql))
|
||||
{
|
||||
Base::set_deleted_key(key_type(key_type::KeyType_Deleted));
|
||||
#if !IL2CPP_USE_SPARSEHASH
|
||||
Base::set_empty_key(key_type(key_type::KeyType_Empty));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<class Value,
|
||||
class HashFcn = SPARSEHASH_HASH<Value>,
|
||||
class EqualKey = std::equal_to<Value>,
|
||||
class Alloc = GOOGLE_NAMESPACE::libc_allocator_with_realloc<KeyWrapper<Value> > >
|
||||
class Il2CppReaderWriterLockedHashSet
|
||||
{
|
||||
public:
|
||||
typedef typename Il2CppHashSet<Value, HashFcn, EqualKey, Alloc>::key_type key_type;
|
||||
typedef typename Il2CppHashSet<Value, HashFcn, EqualKey, Alloc>::size_type size_type;
|
||||
typedef typename Il2CppHashSet<Value, HashFcn, EqualKey, Alloc>::const_iterator const_iterator;
|
||||
typedef typename Il2CppHashSet<Value, HashFcn, EqualKey, Alloc>::iterator iterator;
|
||||
typedef typename Il2CppHashSet<Value, HashFcn, EqualKey, Alloc>::hasher hasher;
|
||||
|
||||
explicit Il2CppReaderWriterLockedHashSet(size_type n = 0,
|
||||
const hasher& hf = hasher(),
|
||||
const EqualKey& eql = EqualKey()) :
|
||||
hashSet(n, hf, eql)
|
||||
{
|
||||
}
|
||||
|
||||
bool TryGet(const Value& findValue, Value* value)
|
||||
{
|
||||
il2cpp::os::FastReaderReaderWriterAutoSharedLock readerLock(&lock);
|
||||
const_iterator iter = hashSet.find(findValue);
|
||||
if (iter != hashSet.end())
|
||||
{
|
||||
*value = *iter;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Add(const Value& value)
|
||||
{
|
||||
il2cpp::os::FastReaderReaderWriterAutoExclusiveLock writerLock(&lock);
|
||||
return hashSet.insert(value).second;
|
||||
}
|
||||
|
||||
Value GetOrAdd(const Value& value)
|
||||
{
|
||||
il2cpp::os::FastReaderReaderWriterAutoExclusiveLock writerLock(&lock);
|
||||
auto inserted = hashSet.insert(value);
|
||||
if (inserted.second)
|
||||
return value;
|
||||
return *(inserted.first);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
il2cpp::os::FastReaderReaderWriterAutoExclusiveLock writerLock(&lock);
|
||||
hashSet.clear();
|
||||
}
|
||||
|
||||
void Resize(size_t size)
|
||||
{
|
||||
il2cpp::os::FastReaderReaderWriterAutoExclusiveLock writerLock(&lock);
|
||||
hashSet.resize(size);
|
||||
}
|
||||
|
||||
private:
|
||||
il2cpp::os::FastReaderReaderWriterLock lock;
|
||||
Il2CppHashSet<Value, HashFcn, EqualKey, Alloc> hashSet;
|
||||
};
|
||||
44
Libraries/libil2cpp/include/utils/KeyWrapper.h
Normal file
44
Libraries/libil2cpp/include/utils/KeyWrapper.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
template<class T>
|
||||
struct KeyWrapper
|
||||
{
|
||||
typedef T wrapped_type;
|
||||
typedef KeyWrapper<T> self_type;
|
||||
|
||||
enum KeyTypeEnum { KeyType_Normal, KeyType_Empty, KeyType_Deleted };
|
||||
|
||||
KeyTypeEnum type;
|
||||
T key;
|
||||
|
||||
KeyWrapper() : type(KeyType_Normal), key(T()) {}
|
||||
KeyWrapper(KeyTypeEnum type_) : type(type_), key(T()) {}
|
||||
KeyWrapper(const T& key_) : key(key_), type(KeyType_Normal) {}
|
||||
KeyWrapper(const self_type& other) : type(other.type), key(other.key) {}
|
||||
|
||||
operator const T&() const { return key; }
|
||||
bool isNormal() const { return (type == KeyType_Normal); }
|
||||
|
||||
template<typename KeyComparer>
|
||||
struct EqualsComparer
|
||||
{
|
||||
EqualsComparer(KeyComparer keyComparer) :
|
||||
m_KeyComparer(keyComparer)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const KeyWrapper<T>& left, const KeyWrapper<T>& right) const
|
||||
{
|
||||
if (left.type != right.type)
|
||||
return false;
|
||||
|
||||
if (!left.isNormal())
|
||||
return true;
|
||||
|
||||
return m_KeyComparer(left.key, right.key);
|
||||
}
|
||||
|
||||
private:
|
||||
KeyComparer m_KeyComparer;
|
||||
};
|
||||
};
|
||||
20
Libraries/libil2cpp/include/utils/Logging.h
Normal file
20
Libraries/libil2cpp/include/utils/Logging.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class LIBIL2CPP_CODEGEN_API Logging
|
||||
{
|
||||
public:
|
||||
static void Write(const char* format, ...);
|
||||
static void SetLogCallback(Il2CppLogCallback method);
|
||||
static bool IsLogCallbackSet();
|
||||
|
||||
private:
|
||||
static Il2CppLogCallback s_Callback;
|
||||
};
|
||||
}
|
||||
}
|
||||
19
Libraries/libil2cpp/include/utils/MarshalingUtils.h
Normal file
19
Libraries/libil2cpp/include/utils/MarshalingUtils.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
|
||||
struct Il2CppInteropData;
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class MarshalingUtils
|
||||
{
|
||||
public:
|
||||
static void MarshalStructToNative(void* managedStructure, void* marshaledStructure, const Il2CppInteropData* interopData);
|
||||
static void MarshalStructFromNative(void* marshaledStructure, void* managedStructure, const Il2CppInteropData* interopData);
|
||||
static bool MarshalFreeStruct(void* marshaledStructure, const Il2CppInteropData* interopData);
|
||||
};
|
||||
} // namespace utils
|
||||
} // namespace il2cpp
|
||||
115
Libraries/libil2cpp/include/utils/MathUtils.h
Normal file
115
Libraries/libil2cpp/include/utils/MathUtils.h
Normal file
@@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
namespace MathUtils
|
||||
{
|
||||
// Do math on low/high part separately as 64-bit integers because otherwise
|
||||
// we might easily overflow during initial multiplication
|
||||
inline int64_t A_Times_B_DividedBy_C(int64_t multiplicand, int64_t multiplier, int64_t divisor)
|
||||
{
|
||||
IL2CPP_ASSERT((llabs(divisor) & (1LL << 62)) == 0 && "Can't divide by numbers with absolute value larger than 2^62 - 1.");
|
||||
bool resultIsNegative = static_cast<uint64_t>(multiplicand ^ multiplier ^ divisor) >> 63; // Result is negative if odd number of operands are negative
|
||||
|
||||
multiplicand = llabs(multiplicand);
|
||||
IL2CPP_ASSERT(multiplicand > 0 && "Can't multiply by -2^63.");
|
||||
|
||||
multiplier = llabs(multiplier);
|
||||
IL2CPP_ASSERT(multiplier > 0 && "Can't multiply by -2^63.");
|
||||
|
||||
divisor = llabs(divisor); // We already asserted on divisor size
|
||||
|
||||
uint64_t multiplicand_low = multiplicand & 0xFFFFFFFF;
|
||||
uint64_t multiplicand_high = multiplicand >> 32;
|
||||
|
||||
uint64_t multiplier_low = multiplier & 0xFFFFFFFF;
|
||||
uint64_t multiplier_high = multiplier >> 32;
|
||||
|
||||
// We're gonna assume our multiplicated value is 128-bit integer
|
||||
// so we're gonna compose it of two uint64_t's
|
||||
// a * b =
|
||||
// (a_high * 2^32 + a_low) * (b_high * 2^32 + b_low) =
|
||||
// a_high * b_high * 2^64 + (a_high * b_low + a_low * b_high) * 2^32 + a_low * b_low
|
||||
uint64_t dividends[2] =
|
||||
{
|
||||
multiplicand_low * multiplier_low, // low part, bits [0, 63]
|
||||
multiplicand_high * multiplier_high // high part, bits [64, 127]
|
||||
};
|
||||
|
||||
uint64_t resultMid1 = multiplicand_high * multiplier_low + multiplicand_low * multiplier_high; // mid part, bits [32, 95]
|
||||
|
||||
dividends[1] += resultMid1 >> 32; // add the higher bits of mid part ([64, 95]) to high part
|
||||
resultMid1 = (resultMid1 & 0xFFFFFFFF) << 32; // Now this contains the lower bits of mid part ([32, 63])
|
||||
|
||||
// Check for lower part overflow below adding the lower bits of mid part to it
|
||||
// Add carry to high part if overflow occurs
|
||||
if (dividends[0] > std::numeric_limits<uint64_t>::max() - resultMid1)
|
||||
dividends[1]++;
|
||||
|
||||
dividends[0] += resultMid1; // add the lower bits of mid part to low part
|
||||
|
||||
// At this point, we got our whole divident 128-bit value inside 'dividends'
|
||||
|
||||
uint64_t workValue = 0; // Value that we're gonna be dividing
|
||||
uint64_t result = 0; // The final result
|
||||
const uint64_t kOne = 1;
|
||||
int bitIndex = 127; // Current bit that we're gonna be add to the workValue
|
||||
|
||||
// Let's find the starting point for our division
|
||||
// We'll keep adding bits from our divident to the workValue until it's higher than the divisor
|
||||
// We did divisor = llabs(divisor) earlier, so cast to unsigned is safe
|
||||
while (workValue < static_cast<uint64_t>(divisor))
|
||||
{
|
||||
workValue <<= 1;
|
||||
|
||||
if (bitIndex > -1)
|
||||
{
|
||||
workValue |= (dividends[bitIndex / 64] & (kOne << (bitIndex % 64))) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bitIndex--;
|
||||
}
|
||||
|
||||
// Main division loop
|
||||
for (; bitIndex > -2 || workValue >= static_cast<uint64_t>(divisor); bitIndex--)
|
||||
{
|
||||
result <<= 1; // Shift result left
|
||||
|
||||
// Since it's binary, the division result can be only 0 and 1
|
||||
// It's 1 if workValue is higher or equal to divisor
|
||||
if (workValue >= static_cast<uint64_t>(divisor))
|
||||
{
|
||||
workValue -= static_cast<uint64_t>(divisor);
|
||||
result++;
|
||||
}
|
||||
|
||||
// Shift work value to the left and append the next bit of our dividend
|
||||
IL2CPP_ASSERT((workValue & (1LL << 63)) == 0 && "overflow!");
|
||||
|
||||
if (bitIndex > -1)
|
||||
{
|
||||
workValue <<= 1;
|
||||
workValue |= (dividends[bitIndex / 64] & (kOne << (bitIndex % 64))) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Negate result if it's supposed to be negative
|
||||
if (resultIsNegative)
|
||||
return -static_cast<int64_t>(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Libraries/libil2cpp/include/utils/Memory.h
Normal file
31
Libraries/libil2cpp/include/utils/Memory.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
struct LIBIL2CPP_CODEGEN_API Memory
|
||||
{
|
||||
static void SetMemoryCallbacks(Il2CppMemoryCallbacks* callbacks);
|
||||
|
||||
static void* Malloc(size_t size);
|
||||
static void* AlignedMalloc(size_t size, size_t alignment);
|
||||
static void Free(void* memory);
|
||||
static void AlignedFree(void* memory);
|
||||
static void* Calloc(size_t count, size_t size);
|
||||
static void* Realloc(void* memory, size_t newSize);
|
||||
static void* AlignedRealloc(void* memory, size_t newSize, size_t alignment);
|
||||
};
|
||||
} /* namespace utils */
|
||||
} /* namespace il2cpp */
|
||||
|
||||
#define IL2CPP_MALLOC(size) il2cpp::utils::Memory::Malloc(size)
|
||||
#define IL2CPP_MALLOC_ALIGNED(size, alignment) il2cpp::utils::Memory::AlignedMalloc(size, alignment)
|
||||
#define IL2CPP_MALLOC_ZERO(size) il2cpp::utils::Memory::Calloc(1,size)
|
||||
#define IL2CPP_FREE(memory) il2cpp::utils::Memory::Free(memory)
|
||||
#define IL2CPP_FREE_ALIGNED(memory) il2cpp::utils::Memory::AlignedFree(memory)
|
||||
#define IL2CPP_CALLOC(count, size) il2cpp::utils::Memory::Calloc(count,size)
|
||||
#define IL2CPP_REALLOC(memory, newSize) il2cpp::utils::Memory::Realloc(memory,newSize)
|
||||
#define IL2CPP_REALLOC_ALIGNED(memory, newSize, alignment) il2cpp::utils::Memory::AlignedRealloc(memory, newSize, alignment)
|
||||
22
Libraries/libil2cpp/include/utils/MemoryMappedFile.h
Normal file
22
Libraries/libil2cpp/include/utils/MemoryMappedFile.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include "os/File.h"
|
||||
#include "os/Mutex.h"
|
||||
#include "os/MemoryMappedFile.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class MemoryMappedFile
|
||||
{
|
||||
public:
|
||||
static void* Map(os::FileHandle* file);
|
||||
static void* Map(os::FileHandle* file, int64_t length, int64_t offset);
|
||||
static void* Map(os::FileHandle* file, int64_t length, int64_t offset, int32_t access);
|
||||
static bool Unmap(void* address);
|
||||
static bool Unmap(void* address, int64_t length);
|
||||
};
|
||||
}
|
||||
}
|
||||
26
Libraries/libil2cpp/include/utils/MemoryPool.h
Normal file
26
Libraries/libil2cpp/include/utils/MemoryPool.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class MemoryPool
|
||||
{
|
||||
public:
|
||||
MemoryPool();
|
||||
MemoryPool(size_t initialSize);
|
||||
~MemoryPool();
|
||||
void* Malloc(size_t size);
|
||||
void* Calloc(size_t count, size_t size);
|
||||
private:
|
||||
struct Region;
|
||||
typedef std::list<Region*> RegionList;
|
||||
|
||||
Region* AddRegion(size_t size);
|
||||
|
||||
RegionList m_Regions;
|
||||
};
|
||||
} /* namespace utils */
|
||||
} /* namespace il2cpp */
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "il2cpp-config.h"
|
||||
|
||||
#if !IL2CPP_SANITIZE_ADDRESS
|
||||
#error MemoryPoolAddressSanitizer should only be used when the address sanitizer is enabled
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
// Use system allocators with the address sanitizer, so that it can catch
|
||||
// problems with memory access that might happen when our memory pool is
|
||||
// used incorrectly.
|
||||
class MemoryPoolAddressSanitizer
|
||||
{
|
||||
public:
|
||||
MemoryPoolAddressSanitizer();
|
||||
MemoryPoolAddressSanitizer(size_t initialSize);
|
||||
~MemoryPoolAddressSanitizer();
|
||||
void* Malloc(size_t size);
|
||||
void* Calloc(size_t count, size_t size);
|
||||
private:
|
||||
std::vector<void*> m_Allocations;
|
||||
};
|
||||
} /* namespace utils */
|
||||
} /* namespace il2cpp */
|
||||
31
Libraries/libil2cpp/include/utils/MemoryRead.h
Normal file
31
Libraries/libil2cpp/include/utils/MemoryRead.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <memory.h>
|
||||
#include "il2cpp-api-types.h"
|
||||
|
||||
// unaligned safe reading
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
static inline Il2CppChar ReadChar(const char* p) { Il2CppChar val; memcpy(&val, p, sizeof(Il2CppChar)); return val; }
|
||||
|
||||
static inline uint16_t Read16(const char* p) { uint16_t val; memcpy(&val, p, sizeof(uint16_t)); return val; }
|
||||
static inline uint32_t Read32(const char* p) { uint32_t val; memcpy(&val, p, sizeof(uint32_t)); return val; }
|
||||
static inline uint64_t Read64(const char* p) { uint64_t val; memcpy(&val, p, sizeof(uint64_t)); return val; }
|
||||
static inline float ReadFloat(const char* p) { float val; memcpy(&val, p, sizeof(float)); return val; }
|
||||
static inline double ReadDouble(const char* p) { double val; memcpy(&val, p, sizeof(double)); return val; }
|
||||
|
||||
static inline Il2CppChar ReadChar(const char** p) { Il2CppChar val; memcpy(&val, *p, sizeof(Il2CppChar)); *p += sizeof(Il2CppChar); return val; }
|
||||
static inline uint8_t Read8(const char** p) { uint8_t val; memcpy(&val, *p, sizeof(uint8_t)); *p += sizeof(uint8_t); return val; }
|
||||
static inline uint16_t Read16(const char** p) { uint16_t val; memcpy(&val, *p, sizeof(uint16_t)); *p += sizeof(uint16_t); return val; }
|
||||
static inline uint32_t Read32(const char** p) { uint32_t val; memcpy(&val, *p, sizeof(uint32_t)); *p += sizeof(uint32_t); return val; }
|
||||
static inline uint64_t Read64(const char** p) { uint64_t val; memcpy(&val, *p, sizeof(uint64_t)); *p += sizeof(uint64_t); return val; }
|
||||
static inline float ReadFloat(const char** p) { float val; memcpy(&val, *p, sizeof(float)); *p += sizeof(float); return val; }
|
||||
static inline double ReadDouble(const char** p) { double val; memcpy(&val, *p, sizeof(double)); *p += sizeof(double); return val; }
|
||||
|
||||
uint32_t ReadCompressedUInt32(const char** p);
|
||||
int32_t ReadCompressedInt32(const char** p);
|
||||
} /* utils */
|
||||
} /* il2cpp */
|
||||
55
Libraries/libil2cpp/include/utils/MemoryUtils.h
Normal file
55
Libraries/libil2cpp/include/utils/MemoryUtils.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "xxhash.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class MemoryUtils
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
static int32_t MemCmpRef(T* left, T* right)
|
||||
{
|
||||
return memcmp(left, right, sizeof(T));
|
||||
}
|
||||
|
||||
#if IL2CPP_TINY
|
||||
template<typename T>
|
||||
static int32_t MemHashRef(T* val)
|
||||
{
|
||||
return XXH32(val, sizeof(T), 0x8f37154b);
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
#define DECL_MEMCMP_NUM(typ) template<> inline int32_t MemoryUtils::MemCmpRef<typ>(typ* left, typ* right) { return (*right > *left) ? -1 : (*right < *left) ? 1 : 0; }
|
||||
DECL_MEMCMP_NUM(int8_t)
|
||||
DECL_MEMCMP_NUM(int16_t)
|
||||
DECL_MEMCMP_NUM(int32_t)
|
||||
DECL_MEMCMP_NUM(int64_t)
|
||||
DECL_MEMCMP_NUM(uint8_t)
|
||||
DECL_MEMCMP_NUM(uint16_t)
|
||||
DECL_MEMCMP_NUM(uint32_t)
|
||||
DECL_MEMCMP_NUM(uint64_t)
|
||||
// don't think this will give the right result for NaNs and such
|
||||
DECL_MEMCMP_NUM(float)
|
||||
DECL_MEMCMP_NUM(double)
|
||||
#undef DECL_MEMCMP_NUM
|
||||
|
||||
#define DECL_MEMHASH_NUM(typ) template<> inline int32_t MemoryUtils::MemHashRef(typ* val) { return (int32_t)(*val); }
|
||||
DECL_MEMHASH_NUM(int8_t)
|
||||
DECL_MEMHASH_NUM(int16_t)
|
||||
DECL_MEMHASH_NUM(int32_t)
|
||||
DECL_MEMHASH_NUM(uint8_t)
|
||||
DECL_MEMHASH_NUM(uint16_t)
|
||||
DECL_MEMHASH_NUM(uint32_t)
|
||||
DECL_MEMHASH_NUM(float)
|
||||
#undef DECL_MEMHASH_NUM
|
||||
|
||||
template<> inline int32_t MemoryUtils::MemHashRef(int64_t* val) { int64_t k = *val; return (int32_t)(k & 0xffffffff) ^ (int32_t)((k >> 32) & 0xffffffff); }
|
||||
template<> inline int32_t MemoryUtils::MemHashRef(uint64_t* val) { return MemHashRef(reinterpret_cast<int64_t*>(val)); }
|
||||
template<> inline int32_t MemoryUtils::MemHashRef(double* val) { return MemHashRef(reinterpret_cast<int64_t*>(val)); }
|
||||
} // namespace utils
|
||||
} // namespace il2cpp
|
||||
34
Libraries/libil2cpp/include/utils/New.h
Normal file
34
Libraries/libil2cpp/include/utils/New.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
|
||||
#if IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_XBOXONE
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <new>
|
||||
|
||||
inline void* operator new(size_t size, int alignment)
|
||||
{
|
||||
void* result = NULL;
|
||||
#if IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_XBOXONE
|
||||
result = _aligned_malloc(size, alignment);
|
||||
#elif IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_PSP2
|
||||
result = memalign(alignment, size);
|
||||
#else
|
||||
if (posix_memalign(&result, size, alignment))
|
||||
result = NULL;
|
||||
#endif
|
||||
if (!result)
|
||||
throw std::bad_alloc();
|
||||
return result;
|
||||
}
|
||||
|
||||
#if IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_XBOXONE // Visual C++ warns if new is overridden but delete is not.
|
||||
inline void operator delete(void* ptr, int alignment) throw ()
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
17
Libraries/libil2cpp/include/utils/NonCopyable.h
Normal file
17
Libraries/libil2cpp/include/utils/NonCopyable.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class NonCopyable
|
||||
{
|
||||
public:
|
||||
NonCopyable() {}
|
||||
|
||||
private:
|
||||
NonCopyable(const NonCopyable&);
|
||||
NonCopyable& operator=(const NonCopyable&);
|
||||
};
|
||||
}
|
||||
}
|
||||
18
Libraries/libil2cpp/include/utils/Output.h
Normal file
18
Libraries/libil2cpp/include/utils/Output.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
|
||||
struct Il2CppString;
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class LIBIL2CPP_CODEGEN_API Output
|
||||
{
|
||||
public:
|
||||
static void WriteToStdout(const char* message);
|
||||
static void WriteToStderr(const char* message);
|
||||
};
|
||||
}
|
||||
}
|
||||
90
Libraries/libil2cpp/include/utils/PathUtils.h
Normal file
90
Libraries/libil2cpp/include/utils/PathUtils.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
#include "il2cpp-config.h"
|
||||
#include <string>
|
||||
#include "StringViewUtils.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
namespace PathUtils
|
||||
{
|
||||
std::string BasenameNoExtension(const std::string& path);
|
||||
std::string PathNoExtension(const std::string& path);
|
||||
|
||||
template<typename CharType>
|
||||
std::basic_string<CharType> Basename(const utils::StringView<CharType>& path)
|
||||
{
|
||||
if (path.IsEmpty())
|
||||
return std::basic_string<CharType>(1, static_cast<CharType>('.'));
|
||||
|
||||
const size_t pos = path.RFind(IL2CPP_DIR_SEPARATOR);
|
||||
|
||||
// No seperators. Path is filename
|
||||
if (pos == utils::StringView<CharType>::NPos())
|
||||
return std::basic_string<CharType>(path.Str(), path.Length());
|
||||
|
||||
return std::basic_string<CharType>(path.Str() + pos + 1, path.Length() - pos - 1);
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
std::basic_string<CharType> Basename(const std::basic_string<CharType>& path)
|
||||
{
|
||||
return Basename(STRING_TO_STRINGVIEW(path));
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
std::basic_string<CharType> DirectoryName(const utils::StringView<CharType>& path)
|
||||
{
|
||||
if (path.IsEmpty())
|
||||
return std::basic_string<CharType>();
|
||||
|
||||
const size_t pos = path.RFind(IL2CPP_DIR_SEPARATOR);
|
||||
|
||||
if (pos == utils::StringView<CharType>::NPos())
|
||||
return std::basic_string<CharType>(1, static_cast<CharType>('.'));
|
||||
|
||||
if (pos == 0)
|
||||
return std::basic_string<CharType>(1, static_cast<CharType>('/'));
|
||||
|
||||
return std::basic_string<CharType>(path.Str(), pos);
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
std::basic_string<CharType> Combine(const utils::StringView<CharType>& path1, const utils::StringView<CharType>& path2)
|
||||
{
|
||||
std::basic_string<CharType> result;
|
||||
result.reserve(path1.Length() + path2.Length() + 1);
|
||||
result.append(path1.Str(), path1.Length());
|
||||
result.append(1, static_cast<CharType>(IL2CPP_DIR_SEPARATOR));
|
||||
result.append(path2.Str(), path2.Length());
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
std::basic_string<CharType> DirectoryName(const std::basic_string<CharType>& path)
|
||||
{
|
||||
return DirectoryName(STRING_TO_STRINGVIEW(path));
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
std::basic_string<CharType> Combine(const std::basic_string<CharType>& path1, const std::basic_string<CharType>& path2)
|
||||
{
|
||||
return Combine(STRING_TO_STRINGVIEW(path1), STRING_TO_STRINGVIEW(path2));
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
std::basic_string<CharType> Combine(const std::basic_string<CharType>& path1, const utils::StringView<CharType>& path2)
|
||||
{
|
||||
return Combine(STRING_TO_STRINGVIEW(path1), path2);
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
std::basic_string<CharType> Combine(const utils::StringView<CharType>& path1, const std::basic_string<CharType>& path2)
|
||||
{
|
||||
return Combine(path1, STRING_TO_STRINGVIEW(path2));
|
||||
}
|
||||
}
|
||||
} /* utils */
|
||||
} /* il2cpp */
|
||||
17
Libraries/libil2cpp/include/utils/Runtime.h
Normal file
17
Libraries/libil2cpp/include/utils/Runtime.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class LIBIL2CPP_CODEGEN_API Runtime
|
||||
{
|
||||
public:
|
||||
static NORETURN void Abort();
|
||||
static void SetDataDir(const char *path);
|
||||
static std::string GetDataDir();
|
||||
};
|
||||
} // utils
|
||||
} // il2cpp
|
||||
272
Libraries/libil2cpp/include/utils/StringUtils.h
Normal file
272
Libraries/libil2cpp/include/utils/StringUtils.h
Normal file
@@ -0,0 +1,272 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright(c) Unity Technologies, Microsoft Corporation
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "il2cpp-string-types.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
#include "il2cpp-config.h"
|
||||
#include "StringView.h"
|
||||
#include "StringViewUtils.h"
|
||||
#include "Baselib.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class LIBIL2CPP_CODEGEN_API StringUtils
|
||||
{
|
||||
public:
|
||||
static std::string Printf(const char* format, ...);
|
||||
static std::string NPrintf(const char* format, size_t max_n, ...);
|
||||
static std::string Utf16ToUtf8(const Il2CppChar* utf16String);
|
||||
static std::string Utf16ToUtf8(const Il2CppChar* utf16String, int maximumSize);
|
||||
static std::string Utf16ToUtf8(const UTF16String& utf16String);
|
||||
static UTF16String Utf8ToUtf16(const char* utf8String);
|
||||
static UTF16String Utf8ToUtf16(const char* utf8String, size_t length);
|
||||
static UTF16String Utf8ToUtf16(const std::string& utf8String);
|
||||
static char* StringDuplicate(const char *strSource);
|
||||
static Il2CppChar* StringDuplicate(const Il2CppChar* strSource, size_t length);
|
||||
static bool EndsWith(const std::string& string, const std::string& suffix);
|
||||
static Il2CppChar* GetChars(Il2CppString* str);
|
||||
static int32_t GetLength(Il2CppString* str);
|
||||
|
||||
#if IL2CPP_TARGET_WINDOWS
|
||||
static inline std::string NativeStringToUtf8(const Il2CppNativeString& nativeStr)
|
||||
{
|
||||
IL2CPP_ASSERT(nativeStr.length() < static_cast<size_t>(std::numeric_limits<int>::max()));
|
||||
return Utf16ToUtf8(nativeStr.c_str(), static_cast<int>(nativeStr.length()));
|
||||
}
|
||||
|
||||
static inline std::string NativeStringToUtf8(const Il2CppNativeChar* nativeStr)
|
||||
{
|
||||
return Utf16ToUtf8(nativeStr);
|
||||
}
|
||||
|
||||
static inline std::string NativeStringToUtf8(const Il2CppNativeChar* nativeStr, uint32_t length)
|
||||
{
|
||||
IL2CPP_ASSERT(length < static_cast<uint32_t>(std::numeric_limits<int>::max()));
|
||||
return Utf16ToUtf8(nativeStr, static_cast<int>(length));
|
||||
}
|
||||
|
||||
static inline Il2CppNativeString Utf8ToNativeString(const std::string& str)
|
||||
{
|
||||
IL2CPP_ASSERT(str.length() < static_cast<size_t>(std::numeric_limits<int>::max()));
|
||||
return Utf8ToUtf16(str.c_str(), str.length());
|
||||
}
|
||||
|
||||
static inline Il2CppNativeString Utf8ToNativeString(const char* str)
|
||||
{
|
||||
return Utf8ToUtf16(str);
|
||||
}
|
||||
#else
|
||||
static inline std::string NativeStringToUtf8(Il2CppNativeString& nativeStr)
|
||||
{
|
||||
return nativeStr;
|
||||
}
|
||||
|
||||
static inline std::string NativeStringToUtf8(const Il2CppNativeChar* nativeStr)
|
||||
{
|
||||
return nativeStr;
|
||||
}
|
||||
|
||||
static inline std::string NativeStringToUtf8(const Il2CppNativeChar* nativeStr, uint32_t length)
|
||||
{
|
||||
return std::string(nativeStr, length);
|
||||
}
|
||||
|
||||
static inline Il2CppNativeString Utf8ToNativeString(const std::string& str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
static inline Il2CppNativeString Utf8ToNativeString(const char* str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename CharType, size_t N>
|
||||
static inline size_t LiteralLength(const CharType(&str)[N])
|
||||
{
|
||||
return N - 1;
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
static size_t StrLen(const CharType* str)
|
||||
{
|
||||
size_t length = 0;
|
||||
while (*str)
|
||||
{
|
||||
str++;
|
||||
length++;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
template <typename CharType>
|
||||
static inline bool Equals(const StringView<CharType>& left, const StringView<CharType>& right)
|
||||
{
|
||||
if (left.Length() != right.Length())
|
||||
return false;
|
||||
|
||||
return memcmp(left.Str(), right.Str(), left.Length() * sizeof(CharType)) == 0;
|
||||
}
|
||||
|
||||
template <typename CharType, size_t rightLength>
|
||||
static inline bool Equals(const StringView<CharType>& left, const CharType (&right)[rightLength])
|
||||
{
|
||||
if (left.Length() != rightLength - 1)
|
||||
return false;
|
||||
|
||||
return memcmp(left.Str(), right, (rightLength - 1) * sizeof(CharType)) == 0;
|
||||
}
|
||||
|
||||
template <typename CharType>
|
||||
static inline bool StartsWith(const StringView<CharType>& left, const StringView<CharType>& right)
|
||||
{
|
||||
if (left.Length() < right.Length())
|
||||
return false;
|
||||
|
||||
return memcmp(left.Str(), right.Str(), right.Length() * sizeof(CharType)) == 0;
|
||||
}
|
||||
|
||||
template <typename CharType, size_t rightLength>
|
||||
static inline bool StartsWith(const StringView<CharType>& left, const CharType(&right)[rightLength])
|
||||
{
|
||||
if (left.Length() < rightLength - 1)
|
||||
return false;
|
||||
|
||||
return memcmp(left.Str(), right, (rightLength - 1) * sizeof(CharType)) == 0;
|
||||
}
|
||||
|
||||
// Taken from github.com/Microsoft/referencesource/blob/master/mscorlib/system/string.cs
|
||||
template<typename CharType>
|
||||
static inline size_t Hash(const CharType *str, size_t length)
|
||||
{
|
||||
IL2CPP_ASSERT(length <= static_cast<size_t>(std::numeric_limits<int>::max()));
|
||||
|
||||
size_t hash1 = 5381;
|
||||
size_t hash2 = hash1;
|
||||
size_t i = 0;
|
||||
|
||||
CharType c;
|
||||
const CharType* s = str;
|
||||
while (true)
|
||||
{
|
||||
if (i++ >= length)
|
||||
break;
|
||||
c = s[0];
|
||||
hash1 = ((hash1 << 5) + hash1) ^ c;
|
||||
if (i++ >= length)
|
||||
break;
|
||||
c = s[1];
|
||||
hash2 = ((hash2 << 5) + hash2) ^ c;
|
||||
s += 2;
|
||||
}
|
||||
|
||||
return hash1 + (hash2 * 1566083941);
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
static inline size_t Hash(const CharType *str)
|
||||
{
|
||||
size_t hash1 = 5381;
|
||||
size_t hash2 = hash1;
|
||||
|
||||
CharType c;
|
||||
const CharType* s = str;
|
||||
while ((c = s[0]) != 0)
|
||||
{
|
||||
hash1 = ((hash1 << 5) + hash1) ^ c;
|
||||
c = s[1];
|
||||
if (c == 0)
|
||||
break;
|
||||
hash2 = ((hash2 << 5) + hash2) ^ c;
|
||||
s += 2;
|
||||
}
|
||||
|
||||
return hash1 + (hash2 * 1566083941);
|
||||
}
|
||||
|
||||
template<typename StringType>
|
||||
struct StringHasher
|
||||
{
|
||||
typedef typename StringType::value_type CharType;
|
||||
|
||||
size_t operator()(const StringType& value) const
|
||||
{
|
||||
return Hash(value.c_str(), value.length());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename CharType>
|
||||
struct StringHasher<const CharType*>
|
||||
{
|
||||
size_t operator()(const CharType* value) const
|
||||
{
|
||||
return Hash(value);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
static inline const baselib_char16_t* NativeStringToBaselib(const Il2CppNativeChar* str)
|
||||
{
|
||||
static_assert(sizeof(Il2CppNativeChar) == sizeof(baselib_char16_t), "type sizes should match");
|
||||
return reinterpret_cast<const baselib_char16_t*>(str);
|
||||
}
|
||||
#else
|
||||
static inline const char* NativeStringToBaselib(const Il2CppNativeChar* str)
|
||||
{
|
||||
static_assert(sizeof(Il2CppNativeChar) == sizeof(char), "type sizes should match");
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
} /* utils */
|
||||
} /* il2cpp */
|
||||
|
||||
// Assumes str is not NULL
|
||||
#if defined(_MSC_VER)
|
||||
#define DECLARE_IL2CPP_STRING_AS_STRING_VIEW_OF_NATIVE_CHARS(variableName, str) \
|
||||
il2cpp::utils::StringView<Il2CppNativeChar> variableName(reinterpret_cast<Il2CppString*>(str)->chars, reinterpret_cast<Il2CppString*>(str)->length);
|
||||
#define DECLARE_IL2CPP_CHAR_PTR_AS_STRING_VIEW_OF_NATIVE_CHARS(variableName, str) \
|
||||
il2cpp::utils::StringView<Il2CppNativeChar> variableName(str, il2cpp::utils::StringUtils::StrLen (str));
|
||||
#define DECLARE_NATIVE_C_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(variableName, str) \
|
||||
il2cpp::utils::StringView<Il2CppChar> variableName(str, wcslen(str));
|
||||
#define DECLARE_NATIVE_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(variableName, str) \
|
||||
il2cpp::utils::StringView<Il2CppChar> variableName = STRING_TO_STRINGVIEW(str);
|
||||
#else
|
||||
#define DECLARE_IL2CPP_STRING_AS_STRING_VIEW_OF_NATIVE_CHARS(variableName, str) \
|
||||
Il2CppNativeString variableName##_native_string_storage = il2cpp::utils::StringUtils::Utf16ToUtf8(reinterpret_cast<Il2CppString*>(str)->chars, reinterpret_cast<Il2CppString*>(str)->length); \
|
||||
il2cpp::utils::StringView<Il2CppNativeChar> variableName(variableName##_native_string_storage.c_str(), variableName##_native_string_storage.length());
|
||||
#define DECLARE_IL2CPP_CHAR_PTR_AS_STRING_VIEW_OF_NATIVE_CHARS(variableName, str) \
|
||||
Il2CppNativeString variableName##_native_string_storage = il2cpp::utils::StringUtils::Utf16ToUtf8(str, il2cpp::utils::StringUtils::StrLen (str)); \
|
||||
il2cpp::utils::StringView<Il2CppNativeChar> variableName(variableName##_native_string_storage.c_str(), variableName##_native_string_storage.length());
|
||||
#define DECLARE_NATIVE_C_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(variableName, str) \
|
||||
UTF16String variableName##_utf16String = il2cpp::utils::StringUtils::Utf8ToUtf16(str); \
|
||||
il2cpp::utils::StringView<Il2CppChar> variableName = STRING_TO_STRINGVIEW(variableName##_utf16String);
|
||||
#define DECLARE_NATIVE_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS DECLARE_NATIVE_C_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS
|
||||
#endif
|
||||
202
Libraries/libil2cpp/include/utils/StringView.h
Normal file
202
Libraries/libil2cpp/include/utils/StringView.h
Normal file
@@ -0,0 +1,202 @@
|
||||
#pragma once
|
||||
#include "il2cpp-config.h"
|
||||
#include <limits.h>
|
||||
#if IL2CPP_TARGET_WINDOWS
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#if IL2CPP_TARGET_LINUX
|
||||
#define GCC_VERSION (__GNUC__ * 10000 \
|
||||
+ __GNUC_MINOR__ * 100 \
|
||||
+ __GNU_PATCHLEVEL__)
|
||||
#endif
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
template<typename CharType>
|
||||
class StringView
|
||||
{
|
||||
private:
|
||||
const CharType* m_String;
|
||||
size_t m_Length;
|
||||
|
||||
// Intended to only be used by Empty()
|
||||
inline StringView() :
|
||||
m_String(NULL),
|
||||
m_Length(0)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
template<size_t Length>
|
||||
inline StringView(const CharType(&str)[Length]) :
|
||||
m_String(str), m_Length(Length - 1)
|
||||
{
|
||||
}
|
||||
|
||||
inline StringView(const CharType* str, size_t length) :
|
||||
m_String(str), m_Length(length)
|
||||
{
|
||||
IL2CPP_ASSERT(str != NULL);
|
||||
}
|
||||
|
||||
inline StringView(const CharType* str, size_t startIndex, size_t length) :
|
||||
m_String(str + startIndex), m_Length(length)
|
||||
{
|
||||
IL2CPP_ASSERT(str != NULL);
|
||||
}
|
||||
|
||||
inline StringView(const StringView<CharType>& str, size_t startIndex, size_t length) :
|
||||
m_String(str.Str() + startIndex),
|
||||
m_Length(length)
|
||||
{
|
||||
IL2CPP_ASSERT(startIndex + length <= str.Length());
|
||||
}
|
||||
|
||||
// This is to work around a bug in gcc (24666) where arrays decay to pointers too fast
|
||||
// This is known to be fixed by at least 7.3.0
|
||||
#if IL2CPP_TARGET_LINUX && GCC_VERSION < 70300
|
||||
inline StringView(const char* str) :
|
||||
m_String(str), m_Length(strlen(str))
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline const CharType* Str() const
|
||||
{
|
||||
return m_String;
|
||||
}
|
||||
|
||||
inline size_t Length() const
|
||||
{
|
||||
return m_Length;
|
||||
}
|
||||
|
||||
inline CharType operator[](size_t index) const
|
||||
{
|
||||
return m_String[index];
|
||||
}
|
||||
|
||||
inline bool IsNullTerminated() const
|
||||
{
|
||||
return m_String[m_Length] == 0;
|
||||
}
|
||||
|
||||
inline bool IsEmpty() const
|
||||
{
|
||||
return Length() == 0;
|
||||
}
|
||||
|
||||
static inline StringView<CharType> Empty()
|
||||
{
|
||||
return StringView<CharType>();
|
||||
}
|
||||
|
||||
inline size_t Find(CharType c, size_t startIndex = 0) const
|
||||
{
|
||||
const CharType* end = m_String + m_Length;
|
||||
for (const CharType* ptr = m_String + startIndex; ptr < end; ptr++)
|
||||
{
|
||||
if (*ptr == c)
|
||||
return ptr - m_String;
|
||||
}
|
||||
|
||||
return NPos();
|
||||
}
|
||||
|
||||
inline size_t RFind(CharType c) const
|
||||
{
|
||||
for (const CharType* ptr = m_String + m_Length; ptr-- > m_String;)
|
||||
{
|
||||
if (*ptr == c)
|
||||
return ptr - m_String;
|
||||
}
|
||||
|
||||
return NPos();
|
||||
}
|
||||
|
||||
inline StringView<CharType> SubStr(size_t startIndex, size_t length)
|
||||
{
|
||||
return StringView<CharType>(*this, startIndex, length);
|
||||
}
|
||||
|
||||
inline StringView<CharType> SubStr(size_t startIndex)
|
||||
{
|
||||
return StringView<CharType>(*this, startIndex, Length() - startIndex);
|
||||
}
|
||||
|
||||
inline static size_t NPos()
|
||||
{
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
inline bool TryParseAsInt(int& outResult)
|
||||
{
|
||||
if (Length() == 0)
|
||||
return false;
|
||||
|
||||
int result = 0;
|
||||
bool isNegative = false;
|
||||
const CharType* ptr = m_String;
|
||||
const CharType* end = m_String + m_Length;
|
||||
|
||||
if (ptr[0] == '-')
|
||||
{
|
||||
isNegative = true;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
for (; ptr < end; ptr++)
|
||||
{
|
||||
CharType digit = *ptr;
|
||||
if (digit < '0' || digit > '9')
|
||||
return false;
|
||||
|
||||
int digitNumeric = digit - '0';
|
||||
if (result > INT_MAX / 10)
|
||||
return false;
|
||||
|
||||
result = result * 10;
|
||||
if (result > INT_MAX - digitNumeric)
|
||||
return false;
|
||||
|
||||
result += digitNumeric;
|
||||
}
|
||||
|
||||
if (isNegative)
|
||||
{
|
||||
outResult = -result;
|
||||
}
|
||||
else
|
||||
{
|
||||
outResult = result;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#define StringViewAsNullTerminatedStringOf(CharType, stringView, variableName) \
|
||||
const CharType* variableName; \
|
||||
do \
|
||||
{ \
|
||||
if (!stringView.IsEmpty() && stringView.IsNullTerminated()) \
|
||||
{ \
|
||||
variableName = stringView.Str(); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
CharType* buffer = static_cast<CharType*>(alloca((stringView.Length() + 1) * sizeof(CharType))); \
|
||||
memcpy(buffer, stringView.Str(), stringView.Length() * sizeof(CharType)); \
|
||||
buffer[stringView.Length()] = 0; \
|
||||
variableName = buffer; \
|
||||
} \
|
||||
} \
|
||||
while (false)
|
||||
}
|
||||
}
|
||||
35
Libraries/libil2cpp/include/utils/StringViewUtils.h
Normal file
35
Libraries/libil2cpp/include/utils/StringViewUtils.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "il2cpp-config.h"
|
||||
#include <string>
|
||||
#include "StringView.h"
|
||||
|
||||
#define STRING_TO_STRINGVIEW(sv) il2cpp::utils::StringViewUtils::StringToStringView(sv)
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class StringViewUtils
|
||||
{
|
||||
public:
|
||||
template<typename CharType, typename CharTraits, typename StringAlloc>
|
||||
static StringView<CharType> StringToStringView(const std::basic_string<CharType, CharTraits, StringAlloc>& str)
|
||||
{
|
||||
return StringView<CharType>(str.c_str(), str.length());
|
||||
}
|
||||
|
||||
// This will prevent accidentally assigning temporary values (like function return values)
|
||||
// to a string view. While this protection will only be enabled on C++11 compiles, even those
|
||||
// are enough to catch the bug in our runtime
|
||||
#if IL2CPP_HAS_DELETED_FUNCTIONS
|
||||
template<typename CharType, typename CharTraits, typename StringAlloc>
|
||||
static StringView<CharType> StringToStringView(const std::basic_string<CharType, CharTraits, StringAlloc>&& str)
|
||||
{
|
||||
IL2CPP_ASSERT(0 && "Cannot create stringview into R-value reference");
|
||||
return StringView<CharType>::Empty();
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
}
|
||||
}
|
||||
46
Libraries/libil2cpp/include/utils/TemplateUtils.h
Normal file
46
Libraries/libil2cpp/include/utils/TemplateUtils.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
namespace TemplateUtils
|
||||
{
|
||||
template<typename T, typename U>
|
||||
struct IsSame
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IsSame<T, T>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename B, typename D>
|
||||
struct IsBaseOf
|
||||
{
|
||||
private:
|
||||
template<typename BT, typename DT>
|
||||
struct Converter
|
||||
{
|
||||
operator BT*() const;
|
||||
operator DT*();
|
||||
};
|
||||
|
||||
typedef int16_t Derived;
|
||||
typedef int8_t NotDerived;
|
||||
|
||||
template<typename T>
|
||||
static Derived IsDerived(D*, T);
|
||||
static NotDerived IsDerived(B*, int);
|
||||
|
||||
public:
|
||||
static const bool value = IsSame<B, D>::value || sizeof(IsDerived(Converter<B, D>(), int())) == sizeof(Derived);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
45
Libraries/libil2cpp/include/utils/ThreadSafeFreeList.h
Normal file
45
Libraries/libil2cpp/include/utils/ThreadSafeFreeList.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "Baselib.h"
|
||||
#include "Cpp/mpmc_node_queue.h"
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
typedef baselib::mpmc_node ThreadSafeFreeListNode;
|
||||
|
||||
/// Lockless allocator that keeps instances of T on a free list.
|
||||
///
|
||||
/// T must be derived from ThreadSafeFreeListNode.
|
||||
///
|
||||
template<typename T>
|
||||
struct ThreadSafeFreeList
|
||||
{
|
||||
T* Allocate()
|
||||
{
|
||||
T* instance = m_NodePool.try_pop_front();
|
||||
if (!instance)
|
||||
instance = new T();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void Release(T* instance)
|
||||
{
|
||||
m_NodePool.push_back(instance);
|
||||
}
|
||||
|
||||
~ThreadSafeFreeList()
|
||||
{
|
||||
T* instance;
|
||||
while ((instance = m_NodePool.try_pop_front()) != NULL)
|
||||
delete instance;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
baselib::mpmc_node_queue<T> m_NodePool;
|
||||
};
|
||||
} /* utils */
|
||||
} /* il2cpp */
|
||||
378
Libraries/libil2cpp/include/utils/dynamic_array.h
Normal file
378
Libraries/libil2cpp/include/utils/dynamic_array.h
Normal file
@@ -0,0 +1,378 @@
|
||||
#pragma once
|
||||
|
||||
#include "Memory.h"
|
||||
#include <algorithm> // std::max
|
||||
#include <memory> // std::uninitialized_fill
|
||||
|
||||
// dynamic_array - simplified version of std::vector<T>
|
||||
//
|
||||
// features:
|
||||
// . always uses memcpy for copying elements. Your data structures must be simple and can't have internal pointers / rely on copy constructor.
|
||||
// . EASTL like push_back(void) implementation
|
||||
// Existing std STL implementations implement insertion operations by copying from an element.
|
||||
// For example, resize(size() + 1) creates a throw-away temporary object.
|
||||
// There is no way in existing std STL implementations to add an element to a container without implicitly or
|
||||
// explicitly providing one to copy from (aside from some existing POD optimizations).
|
||||
// For expensive-to-construct objects this creates a potentially serious performance problem.
|
||||
// . grows X2 on reallocation
|
||||
// . small code footprint
|
||||
// . clear actually deallocates memory
|
||||
// . resize does NOT initialize members!
|
||||
//
|
||||
// Changelog:
|
||||
// Added pop_back()
|
||||
// Added assign()
|
||||
// Added clear() - frees the data, use resize(0) to clear w/o freeing
|
||||
// zero allocation for empty array
|
||||
//
|
||||
|
||||
namespace il2cpp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
template<typename T>
|
||||
struct AlignOfType
|
||||
{
|
||||
enum
|
||||
{
|
||||
align = ALIGN_OF(T)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template<typename T, size_t ALIGN = AlignOfType<T>::align>
|
||||
struct dynamic_array
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
align = ALIGN
|
||||
};
|
||||
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
typedef T value_type;
|
||||
typedef size_t size_type;
|
||||
typedef size_t difference_type;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_array() : m_data(NULL), m_size(0), m_capacity(0)
|
||||
{
|
||||
}
|
||||
|
||||
explicit dynamic_array(size_t size)
|
||||
: m_size(size), m_capacity(size)
|
||||
{
|
||||
m_data = allocate(size);
|
||||
}
|
||||
|
||||
dynamic_array(size_t size, T const &init_value)
|
||||
: m_size(size), m_capacity(size)
|
||||
{
|
||||
m_data = allocate(size);
|
||||
std::uninitialized_fill(m_data, m_data + size, init_value);
|
||||
}
|
||||
|
||||
~dynamic_array()
|
||||
{
|
||||
if (owns_data())
|
||||
m_data = deallocate(m_data);
|
||||
}
|
||||
|
||||
dynamic_array(const dynamic_array &other) : m_size(0), m_capacity(0)
|
||||
{
|
||||
m_data = NULL;
|
||||
assign(other.begin(), other.end());
|
||||
}
|
||||
|
||||
dynamic_array &operator=(const dynamic_array &other)
|
||||
{
|
||||
// should not allocate memory unless we have to
|
||||
if (&other != this)
|
||||
assign(other.begin(), other.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (owns_data())
|
||||
m_data = deallocate(m_data);
|
||||
m_size = 0;
|
||||
m_capacity = 0;
|
||||
}
|
||||
|
||||
void assign(const_iterator begin, const_iterator end)
|
||||
{
|
||||
Assert(begin <= end);
|
||||
|
||||
resize_uninitialized(end - begin);
|
||||
memcpy(m_data, begin, m_size * sizeof(T));
|
||||
}
|
||||
|
||||
iterator erase(iterator input_begin, iterator input_end)
|
||||
{
|
||||
Assert(input_begin <= input_end);
|
||||
Assert(input_begin >= begin());
|
||||
Assert(input_end <= end());
|
||||
|
||||
size_t leftOverSize = end() - input_end;
|
||||
memmove(input_begin, input_end, leftOverSize * sizeof(T));
|
||||
m_size -= input_end - input_begin;
|
||||
return input_begin;
|
||||
}
|
||||
|
||||
iterator erase(iterator it)
|
||||
{
|
||||
return erase(it, it + 1);
|
||||
}
|
||||
|
||||
iterator erase_swap_back(iterator it)
|
||||
{
|
||||
m_size--;
|
||||
memcpy(it, end(), sizeof(T));
|
||||
return it;
|
||||
}
|
||||
|
||||
iterator insert(iterator insert_before, const_iterator input_begin, const_iterator input_end)
|
||||
{
|
||||
Assert(input_begin <= input_end);
|
||||
Assert(insert_before >= begin());
|
||||
Assert(insert_before <= end());
|
||||
|
||||
// resize (make sure that insertBefore does not get invalid in the meantime because of a reallocation)
|
||||
size_t insert_before_index = insert_before - begin();
|
||||
size_t elements_to_be_moved = size() - insert_before_index;
|
||||
resize_uninitialized((input_end - input_begin) + size(), true);
|
||||
insert_before = begin() + insert_before_index;
|
||||
|
||||
size_t insertsize = input_end - input_begin;
|
||||
// move to the end of where the inserted data will be
|
||||
memmove(insert_before + insertsize, insert_before, elements_to_be_moved * sizeof(T));
|
||||
// inject input data in the hole we just created
|
||||
memcpy(insert_before, input_begin, insertsize * sizeof(T));
|
||||
|
||||
return insert_before;
|
||||
}
|
||||
|
||||
iterator insert(iterator insertBefore, const T &t) { return insert(insertBefore, &t, &t + 1); }
|
||||
|
||||
void swap(dynamic_array &other) throw ()
|
||||
{
|
||||
std::swap(m_data, other.m_data);
|
||||
std::swap(m_size, other.m_size);
|
||||
std::swap(m_capacity, other.m_capacity);
|
||||
}
|
||||
|
||||
// Returns the memory to the object.
|
||||
// This does not call the constructor for the newly added element.
|
||||
// You are expected to initialize all member variables of the returned data.
|
||||
T &push_back()
|
||||
{
|
||||
if (++m_size > capacity())
|
||||
reserve(std::max<size_t>(capacity() * 2, 1));
|
||||
return back();
|
||||
}
|
||||
|
||||
// push_back but it also calls the constructor for the newly added element.
|
||||
T &push_back_construct()
|
||||
{
|
||||
if (++m_size > capacity())
|
||||
reserve(std::max<size_t>(capacity() * 2, 1));
|
||||
// construct
|
||||
T *ptr = &back();
|
||||
new(ptr) T;
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
// push_back but assigns /t/ to the newly added element.
|
||||
void push_back(const T &t)
|
||||
{
|
||||
push_back() = t;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
Assert(m_size >= 1);
|
||||
m_size--;
|
||||
}
|
||||
|
||||
void resize_uninitialized(size_t size, bool double_on_resize = false)
|
||||
{
|
||||
m_size = size;
|
||||
if (m_size <= capacity())
|
||||
return;
|
||||
|
||||
if (double_on_resize && size < capacity() * 2)
|
||||
size = capacity() * 2;
|
||||
reserve(size);
|
||||
}
|
||||
|
||||
void resize_initialized(size_t size, const T &t = T(), bool double_on_resize = false)
|
||||
{
|
||||
if (size > capacity())
|
||||
{
|
||||
size_t requested_size = size;
|
||||
if (double_on_resize && size < capacity() * 2)
|
||||
requested_size = capacity() * 2;
|
||||
reserve(requested_size);
|
||||
}
|
||||
|
||||
if (size > m_size)
|
||||
std::uninitialized_fill(m_data + m_size, m_data + size, t);
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void reserve(size_t inCapacity)
|
||||
{
|
||||
if (capacity() >= inCapacity)
|
||||
return;
|
||||
|
||||
if (owns_data())
|
||||
{
|
||||
Assert((inCapacity & k_reference_bit) == 0 && "Dynamic array capacity overflow");
|
||||
m_capacity = inCapacity;
|
||||
m_data = reallocate(m_data, inCapacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
T *newData = allocate(inCapacity);
|
||||
memcpy(newData, m_data, m_size * sizeof(T));
|
||||
|
||||
// Invalidate old non-owned data, since using the data from two places is most likely a really really bad idea.
|
||||
#if IL2CPP_DEBUG
|
||||
memset(m_data, 0xCD, capacity() * sizeof(T));
|
||||
#endif
|
||||
|
||||
m_capacity = inCapacity; // and clear reference bit
|
||||
m_data = newData;
|
||||
}
|
||||
}
|
||||
|
||||
void assign_external(T *begin, T *end)
|
||||
{
|
||||
if (owns_data())
|
||||
m_data = deallocate(m_data);
|
||||
m_size = m_capacity = reinterpret_cast<value_type *>(end) - reinterpret_cast<value_type *>(begin);
|
||||
Assert(m_size < k_reference_bit);
|
||||
m_capacity |= k_reference_bit;
|
||||
m_data = begin;
|
||||
}
|
||||
|
||||
void set_owns_data(bool ownsData)
|
||||
{
|
||||
if (ownsData)
|
||||
m_capacity &= ~k_reference_bit;
|
||||
else
|
||||
m_capacity |= k_reference_bit;
|
||||
}
|
||||
|
||||
void shrink_to_fit()
|
||||
{
|
||||
if (owns_data())
|
||||
{
|
||||
m_capacity = m_size;
|
||||
m_data = reallocate(m_data, m_size);
|
||||
}
|
||||
}
|
||||
|
||||
const T &back() const
|
||||
{
|
||||
Assert(m_size != 0);
|
||||
return m_data[m_size - 1];
|
||||
}
|
||||
|
||||
const T &front() const
|
||||
{
|
||||
Assert(m_size != 0);
|
||||
return m_data[0];
|
||||
}
|
||||
|
||||
T &back()
|
||||
{
|
||||
Assert(m_size != 0);
|
||||
return m_data[m_size - 1];
|
||||
}
|
||||
|
||||
T &front()
|
||||
{
|
||||
Assert(m_size != 0);
|
||||
return m_data[0];
|
||||
}
|
||||
|
||||
T *data() { return m_data; }
|
||||
|
||||
T const *data() const { return m_data; }
|
||||
|
||||
bool empty() const { return m_size == 0; }
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
|
||||
size_t capacity() const { return m_capacity & ~k_reference_bit; }
|
||||
|
||||
T const &operator[](size_t index) const
|
||||
{
|
||||
Assert(index < m_size);
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
T &operator[](size_t index)
|
||||
{
|
||||
Assert(index < m_size);
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
T const *begin() const { return m_data; }
|
||||
|
||||
T *begin() { return m_data; }
|
||||
|
||||
T const *end() const { return m_data + m_size; }
|
||||
|
||||
T *end() { return m_data + m_size; }
|
||||
|
||||
bool owns_data() { return (m_capacity & k_reference_bit) == 0; }
|
||||
|
||||
bool equals(const dynamic_array &other) const
|
||||
{
|
||||
if (m_size != other.m_size)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < m_size; i++)
|
||||
{
|
||||
if (!(m_data[i] == other.m_data[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static const size_t k_reference_bit = (size_t)1 << (sizeof(size_t) * 8 - 1);
|
||||
|
||||
T *allocate(size_t size)
|
||||
{
|
||||
return static_cast<T *>(IL2CPP_MALLOC_ALIGNED(size * sizeof(T), align));
|
||||
}
|
||||
|
||||
T *deallocate(T *data)
|
||||
{
|
||||
Assert(owns_data());
|
||||
IL2CPP_FREE_ALIGNED(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
T *reallocate(T *data, size_t size)
|
||||
{
|
||||
Assert(owns_data());
|
||||
return static_cast<T *>(IL2CPP_REALLOC_ALIGNED(data, size * sizeof(T), align));
|
||||
}
|
||||
|
||||
T *m_data;
|
||||
size_t m_size;
|
||||
size_t m_capacity;
|
||||
};
|
||||
} //namespace il2cpp
|
||||
} //namespace utils
|
||||
5
Libraries/libil2cpp/include/utils/sha1.h
Normal file
5
Libraries/libil2cpp/include/utils/sha1.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void sha1_get_digest(const uint8_t* buffer, int buffer_size, uint8_t digest[20]);
|
||||
34
Libraries/libil2cpp/include/utils/utf8-cpp/source/utf8.h
Normal file
34
Libraries/libil2cpp/include/utils/utf8-cpp/source/utf8.h
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
#include "utf8/checked.h"
|
||||
#include "utf8/unchecked.h"
|
||||
|
||||
#endif // header guard
|
||||
327
Libraries/libil2cpp/include/utils/utf8-cpp/source/utf8/checked.h
Normal file
327
Libraries/libil2cpp/include/utils/utf8-cpp/source/utf8/checked.h
Normal file
@@ -0,0 +1,327 @@
|
||||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
#include "core.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
// Base for the exceptions that may be thrown from the library
|
||||
class exception : public ::std::exception {
|
||||
};
|
||||
|
||||
// Exceptions that may be thrown from the library functions.
|
||||
class invalid_code_point : public exception {
|
||||
uint32_t cp;
|
||||
public:
|
||||
invalid_code_point(uint32_t cp) : cp(cp) {}
|
||||
virtual const char* what() const throw() { return "Invalid code point"; }
|
||||
uint32_t code_point() const {return cp;}
|
||||
};
|
||||
|
||||
class invalid_utf8 : public exception {
|
||||
uint8_t u8;
|
||||
public:
|
||||
invalid_utf8 (uint8_t u) : u8(u) {}
|
||||
virtual const char* what() const throw() { return "Invalid UTF-8"; }
|
||||
uint8_t utf8_octet() const {return u8;}
|
||||
};
|
||||
|
||||
class invalid_utf16 : public exception {
|
||||
uint16_t u16;
|
||||
public:
|
||||
invalid_utf16 (uint16_t u) : u16(u) {}
|
||||
virtual const char* what() const throw() { return "Invalid UTF-16"; }
|
||||
uint16_t utf16_word() const {return u16;}
|
||||
};
|
||||
|
||||
class not_enough_room : public exception {
|
||||
public:
|
||||
virtual const char* what() const throw() { return "Not enough space"; }
|
||||
};
|
||||
|
||||
/// The library API - functions intended to be called by the users
|
||||
|
||||
template <typename octet_iterator>
|
||||
octet_iterator append(uint32_t cp, octet_iterator result)
|
||||
{
|
||||
if (!utf8::internal::is_code_point_valid(cp))
|
||||
throw invalid_code_point(cp);
|
||||
|
||||
if (cp < 0x80) // one octet
|
||||
*(result++) = static_cast<uint8_t>(cp);
|
||||
else if (cp < 0x800) { // two octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else if (cp < 0x10000) { // three octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else { // four octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename output_iterator>
|
||||
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
|
||||
{
|
||||
while (start != end) {
|
||||
octet_iterator sequence_start = start;
|
||||
internal::utf_error err_code = utf8::internal::validate_next(start, end);
|
||||
switch (err_code) {
|
||||
case internal::UTF8_OK :
|
||||
for (octet_iterator it = sequence_start; it != start; ++it)
|
||||
*out++ = *it;
|
||||
break;
|
||||
case internal::NOT_ENOUGH_ROOM:
|
||||
throw not_enough_room();
|
||||
case internal::INVALID_LEAD:
|
||||
out = utf8::append (replacement, out);
|
||||
++start;
|
||||
break;
|
||||
case internal::INCOMPLETE_SEQUENCE:
|
||||
case internal::OVERLONG_SEQUENCE:
|
||||
case internal::INVALID_CODE_POINT:
|
||||
out = utf8::append (replacement, out);
|
||||
++start;
|
||||
// just one replacement mark for the sequence
|
||||
while (start != end && utf8::internal::is_trail(*start))
|
||||
++start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename output_iterator>
|
||||
inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
|
||||
{
|
||||
static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
|
||||
return utf8::replace_invalid(start, end, out, replacement_marker);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t next(octet_iterator& it, octet_iterator end)
|
||||
{
|
||||
uint32_t cp = 0;
|
||||
internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
|
||||
switch (err_code) {
|
||||
case internal::UTF8_OK :
|
||||
break;
|
||||
case internal::NOT_ENOUGH_ROOM :
|
||||
throw not_enough_room();
|
||||
case internal::INVALID_LEAD :
|
||||
case internal::INCOMPLETE_SEQUENCE :
|
||||
case internal::OVERLONG_SEQUENCE :
|
||||
throw invalid_utf8(*it);
|
||||
case internal::INVALID_CODE_POINT :
|
||||
throw invalid_code_point(cp);
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t peek_next(octet_iterator it, octet_iterator end)
|
||||
{
|
||||
return utf8::next(it, end);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t prior(octet_iterator& it, octet_iterator start)
|
||||
{
|
||||
// can't do much if it == start
|
||||
if (it == start)
|
||||
throw not_enough_room();
|
||||
|
||||
octet_iterator end = it;
|
||||
// Go back until we hit either a lead octet or start
|
||||
while (utf8::internal::is_trail(*(--it)))
|
||||
if (it == start)
|
||||
throw invalid_utf8(*it); // error - no lead byte in the sequence
|
||||
return utf8::peek_next(it, end);
|
||||
}
|
||||
|
||||
/// Deprecated in versions that include "prior"
|
||||
template <typename octet_iterator>
|
||||
uint32_t previous(octet_iterator& it, octet_iterator pass_start)
|
||||
{
|
||||
octet_iterator end = it;
|
||||
while (utf8::internal::is_trail(*(--it)))
|
||||
if (it == pass_start)
|
||||
throw invalid_utf8(*it); // error - no lead byte in the sequence
|
||||
octet_iterator temp = it;
|
||||
return utf8::next(temp, end);
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename distance_type>
|
||||
void advance (octet_iterator& it, distance_type n, octet_iterator end)
|
||||
{
|
||||
for (distance_type i = 0; i < n; ++i)
|
||||
utf8::next(it, end);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
typename std::iterator_traits<octet_iterator>::difference_type
|
||||
distance (octet_iterator first, octet_iterator last)
|
||||
{
|
||||
typename std::iterator_traits<octet_iterator>::difference_type dist;
|
||||
for (dist = 0; first < last; ++dist)
|
||||
utf8::next(first, last);
|
||||
return dist;
|
||||
}
|
||||
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
|
||||
{
|
||||
while (start != end) {
|
||||
uint32_t cp = utf8::internal::mask16(*start++);
|
||||
// Take care of surrogate pairs first
|
||||
if (utf8::internal::is_lead_surrogate(cp)) {
|
||||
if (start != end) {
|
||||
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
|
||||
if (utf8::internal::is_trail_surrogate(trail_surrogate))
|
||||
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
|
||||
else
|
||||
throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
|
||||
}
|
||||
else
|
||||
throw invalid_utf16(static_cast<uint16_t>(cp));
|
||||
|
||||
}
|
||||
// Lone trail surrogate
|
||||
else if (utf8::internal::is_trail_surrogate(cp))
|
||||
throw invalid_utf16(static_cast<uint16_t>(cp));
|
||||
|
||||
result = utf8::append(cp, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
|
||||
{
|
||||
while (start != end) {
|
||||
uint32_t cp = utf8::next(start, end);
|
||||
if (cp > 0xffff) { //make a surrogate pair
|
||||
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
|
||||
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
|
||||
}
|
||||
else
|
||||
*result++ = static_cast<uint16_t>(cp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
|
||||
{
|
||||
while (start != end)
|
||||
result = utf8::append(*(start++), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
|
||||
{
|
||||
while (start != end)
|
||||
(*result++) = utf8::next(start, end);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// The iterator class
|
||||
template <typename octet_iterator>
|
||||
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
|
||||
octet_iterator it;
|
||||
octet_iterator range_start;
|
||||
octet_iterator range_end;
|
||||
public:
|
||||
iterator () {}
|
||||
explicit iterator (const octet_iterator& octet_it,
|
||||
const octet_iterator& range_start,
|
||||
const octet_iterator& range_end) :
|
||||
it(octet_it), range_start(range_start), range_end(range_end)
|
||||
{
|
||||
if (it < range_start || it > range_end)
|
||||
throw std::out_of_range("Invalid utf-8 iterator position");
|
||||
}
|
||||
// the default "big three" are OK
|
||||
octet_iterator base () const { return it; }
|
||||
uint32_t operator * () const
|
||||
{
|
||||
octet_iterator temp = it;
|
||||
return utf8::next(temp, range_end);
|
||||
}
|
||||
bool operator == (const iterator& rhs) const
|
||||
{
|
||||
if (range_start != rhs.range_start || range_end != rhs.range_end)
|
||||
throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
|
||||
return (it == rhs.it);
|
||||
}
|
||||
bool operator != (const iterator& rhs) const
|
||||
{
|
||||
return !(operator == (rhs));
|
||||
}
|
||||
iterator& operator ++ ()
|
||||
{
|
||||
utf8::next(it, range_end);
|
||||
return *this;
|
||||
}
|
||||
iterator operator ++ (int)
|
||||
{
|
||||
iterator temp = *this;
|
||||
utf8::next(it, range_end);
|
||||
return temp;
|
||||
}
|
||||
iterator& operator -- ()
|
||||
{
|
||||
utf8::prior(it, range_start);
|
||||
return *this;
|
||||
}
|
||||
iterator operator -- (int)
|
||||
{
|
||||
iterator temp = *this;
|
||||
utf8::prior(it, range_start);
|
||||
return temp;
|
||||
}
|
||||
}; // class iterator
|
||||
|
||||
} // namespace utf8
|
||||
|
||||
#endif //header guard
|
||||
|
||||
|
||||
329
Libraries/libil2cpp/include/utils/utf8-cpp/source/utf8/core.h
Normal file
329
Libraries/libil2cpp/include/utils/utf8-cpp/source/utf8/core.h
Normal file
@@ -0,0 +1,329 @@
|
||||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
// The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
|
||||
// You may need to change them to match your system.
|
||||
// These typedefs have the same names as ones from cstdint, or boost/cstdint
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
|
||||
// Helper code - not intended to be directly called by the library users. May be changed at any time
|
||||
namespace internal
|
||||
{
|
||||
// Unicode constants
|
||||
// Leading (high) surrogates: 0xd800 - 0xdbff
|
||||
// Trailing (low) surrogates: 0xdc00 - 0xdfff
|
||||
const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
|
||||
const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
|
||||
const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
|
||||
const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
|
||||
const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
|
||||
const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
|
||||
|
||||
// Maximum valid value for a Unicode code point
|
||||
const uint32_t CODE_POINT_MAX = 0x0010ffffu;
|
||||
|
||||
template<typename octet_type>
|
||||
inline uint8_t mask8(octet_type oc)
|
||||
{
|
||||
return static_cast<uint8_t>(0xff & oc);
|
||||
}
|
||||
template<typename u16_type>
|
||||
inline uint16_t mask16(u16_type oc)
|
||||
{
|
||||
return static_cast<uint16_t>(0xffff & oc);
|
||||
}
|
||||
template<typename octet_type>
|
||||
inline bool is_trail(octet_type oc)
|
||||
{
|
||||
return ((utf8::internal::mask8(oc) >> 6) == 0x2);
|
||||
}
|
||||
|
||||
template <typename u16>
|
||||
inline bool is_lead_surrogate(u16 cp)
|
||||
{
|
||||
return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
|
||||
}
|
||||
|
||||
template <typename u16>
|
||||
inline bool is_trail_surrogate(u16 cp)
|
||||
{
|
||||
return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
|
||||
}
|
||||
|
||||
template <typename u16>
|
||||
inline bool is_surrogate(u16 cp)
|
||||
{
|
||||
return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
|
||||
}
|
||||
|
||||
template <typename u32>
|
||||
inline bool is_code_point_valid(u32 cp)
|
||||
{
|
||||
return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline typename std::iterator_traits<octet_iterator>::difference_type
|
||||
sequence_length(octet_iterator lead_it)
|
||||
{
|
||||
uint8_t lead = utf8::internal::mask8(*lead_it);
|
||||
if (lead < 0x80)
|
||||
return 1;
|
||||
else if ((lead >> 5) == 0x6)
|
||||
return 2;
|
||||
else if ((lead >> 4) == 0xe)
|
||||
return 3;
|
||||
else if ((lead >> 3) == 0x1e)
|
||||
return 4;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename octet_difference_type>
|
||||
inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
|
||||
{
|
||||
if (cp < 0x80) {
|
||||
if (length != 1)
|
||||
return true;
|
||||
}
|
||||
else if (cp < 0x800) {
|
||||
if (length != 2)
|
||||
return true;
|
||||
}
|
||||
else if (cp < 0x10000) {
|
||||
if (length != 3)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
|
||||
|
||||
/// Helper for get_sequence_x
|
||||
template <typename octet_iterator>
|
||||
utf_error increase_safely(octet_iterator& it, octet_iterator end)
|
||||
{
|
||||
if (++it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
if (!utf8::internal::is_trail(*it))
|
||||
return INCOMPLETE_SEQUENCE;
|
||||
|
||||
return UTF8_OK;
|
||||
}
|
||||
|
||||
#define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
|
||||
|
||||
/// get_sequence_x functions decode utf-8 sequences of the length x
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
code_point = utf8::internal::mask8(*it);
|
||||
|
||||
return UTF8_OK;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
code_point = utf8::internal::mask8(*it);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
|
||||
|
||||
return UTF8_OK;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
code_point = utf8::internal::mask8(*it);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point += (*it) & 0x3f;
|
||||
|
||||
return UTF8_OK;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
code_point = utf8::internal::mask8(*it);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
|
||||
code_point += (*it) & 0x3f;
|
||||
|
||||
return UTF8_OK;
|
||||
}
|
||||
|
||||
#undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
{
|
||||
// Save the original value of it so we can go back in case of failure
|
||||
// Of course, it does not make much sense with i.e. stream iterators
|
||||
octet_iterator original_it = it;
|
||||
|
||||
uint32_t cp = 0;
|
||||
// Determine the sequence length based on the lead octet
|
||||
typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
|
||||
const octet_difference_type length = utf8::internal::sequence_length(it);
|
||||
|
||||
// Get trail octets and calculate the code point
|
||||
utf_error err = UTF8_OK;
|
||||
switch (length) {
|
||||
case 0:
|
||||
return INVALID_LEAD;
|
||||
case 1:
|
||||
err = utf8::internal::get_sequence_1(it, end, cp);
|
||||
break;
|
||||
case 2:
|
||||
err = utf8::internal::get_sequence_2(it, end, cp);
|
||||
break;
|
||||
case 3:
|
||||
err = utf8::internal::get_sequence_3(it, end, cp);
|
||||
break;
|
||||
case 4:
|
||||
err = utf8::internal::get_sequence_4(it, end, cp);
|
||||
break;
|
||||
}
|
||||
|
||||
if (err == UTF8_OK) {
|
||||
// Decoding succeeded. Now, security checks...
|
||||
if (utf8::internal::is_code_point_valid(cp)) {
|
||||
if (!utf8::internal::is_overlong_sequence(cp, length)){
|
||||
// Passed! Return here.
|
||||
code_point = cp;
|
||||
++it;
|
||||
return UTF8_OK;
|
||||
}
|
||||
else
|
||||
err = OVERLONG_SEQUENCE;
|
||||
}
|
||||
else
|
||||
err = INVALID_CODE_POINT;
|
||||
}
|
||||
|
||||
// Failure branch - restore the original value of the iterator
|
||||
it = original_it;
|
||||
return err;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
|
||||
uint32_t ignored;
|
||||
return utf8::internal::validate_next(it, end, ignored);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// The library API - functions intended to be called by the users
|
||||
|
||||
// Byte order mark
|
||||
const uint8_t bom[] = {0xef, 0xbb, 0xbf};
|
||||
|
||||
template <typename octet_iterator>
|
||||
octet_iterator find_invalid(octet_iterator start, octet_iterator end)
|
||||
{
|
||||
octet_iterator result = start;
|
||||
while (result != end) {
|
||||
utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
|
||||
if (err_code != internal::UTF8_OK)
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline bool is_valid(octet_iterator start, octet_iterator end)
|
||||
{
|
||||
return (utf8::find_invalid(start, end) == end);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline bool starts_with_bom (octet_iterator it, octet_iterator end)
|
||||
{
|
||||
return (
|
||||
((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
|
||||
((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
|
||||
((it != end) && (utf8::internal::mask8(*it)) == bom[2])
|
||||
);
|
||||
}
|
||||
|
||||
//Deprecated in release 2.3
|
||||
template <typename octet_iterator>
|
||||
inline bool is_bom (octet_iterator it)
|
||||
{
|
||||
return (
|
||||
(utf8::internal::mask8(*it++)) == bom[0] &&
|
||||
(utf8::internal::mask8(*it++)) == bom[1] &&
|
||||
(utf8::internal::mask8(*it)) == bom[2]
|
||||
);
|
||||
}
|
||||
} // namespace utf8
|
||||
|
||||
#endif // header guard
|
||||
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
#include "core.h"
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
namespace unchecked
|
||||
{
|
||||
template <typename octet_iterator>
|
||||
octet_iterator append(uint32_t cp, octet_iterator result)
|
||||
{
|
||||
if (cp < 0x80) // one octet
|
||||
*(result++) = static_cast<uint8_t>(cp);
|
||||
else if (cp < 0x800) { // two octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else if (cp < 0x10000) { // three octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else { // four octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t next(octet_iterator& it)
|
||||
{
|
||||
uint32_t cp = utf8::internal::mask8(*it);
|
||||
typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
|
||||
switch (length) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
it++;
|
||||
cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
|
||||
break;
|
||||
case 3:
|
||||
++it;
|
||||
cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
|
||||
++it;
|
||||
cp += (*it) & 0x3f;
|
||||
break;
|
||||
case 4:
|
||||
++it;
|
||||
cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
|
||||
++it;
|
||||
cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
|
||||
++it;
|
||||
cp += (*it) & 0x3f;
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
return cp;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t peek_next(octet_iterator it)
|
||||
{
|
||||
return utf8::unchecked::next(it);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t prior(octet_iterator& it)
|
||||
{
|
||||
while (utf8::internal::is_trail(*(--it))) ;
|
||||
octet_iterator temp = it;
|
||||
return utf8::unchecked::next(temp);
|
||||
}
|
||||
|
||||
// Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
|
||||
template <typename octet_iterator>
|
||||
inline uint32_t previous(octet_iterator& it)
|
||||
{
|
||||
return utf8::unchecked::prior(it);
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename distance_type>
|
||||
void advance (octet_iterator& it, distance_type n)
|
||||
{
|
||||
for (distance_type i = 0; i < n; ++i)
|
||||
utf8::unchecked::next(it);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
typename std::iterator_traits<octet_iterator>::difference_type
|
||||
distance (octet_iterator first, octet_iterator last)
|
||||
{
|
||||
typename std::iterator_traits<octet_iterator>::difference_type dist;
|
||||
for (dist = 0; first < last; ++dist)
|
||||
utf8::unchecked::next(first);
|
||||
return dist;
|
||||
}
|
||||
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
|
||||
{
|
||||
static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
|
||||
while (start != end) {
|
||||
uint32_t cp = utf8::internal::mask16(*start++);
|
||||
// Take care of surrogate pairs first
|
||||
if (utf8::internal::is_lead_surrogate(cp)) {
|
||||
if (start != end) {
|
||||
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
|
||||
if (utf8::internal::is_trail_surrogate(trail_surrogate))
|
||||
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
|
||||
else
|
||||
cp = replacement_marker;
|
||||
}
|
||||
else
|
||||
cp = replacement_marker;
|
||||
|
||||
}
|
||||
// Lone trail surrogate
|
||||
else if (utf8::internal::is_trail_surrogate(cp))
|
||||
cp = replacement_marker;
|
||||
|
||||
result = utf8::unchecked::append(cp, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
|
||||
{
|
||||
while (start < end) {
|
||||
uint32_t cp = utf8::unchecked::next(start);
|
||||
if (cp > 0xffff) { //make a surrogate pair
|
||||
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
|
||||
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
|
||||
}
|
||||
else
|
||||
*result++ = static_cast<uint16_t>(cp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
|
||||
{
|
||||
while (start != end)
|
||||
result = utf8::unchecked::append(*(start++), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
|
||||
{
|
||||
while (start < end)
|
||||
(*result++) = utf8::unchecked::next(start);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// The iterator class
|
||||
template <typename octet_iterator>
|
||||
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
|
||||
octet_iterator it;
|
||||
public:
|
||||
iterator () {}
|
||||
explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
|
||||
// the default "big three" are OK
|
||||
octet_iterator base () const { return it; }
|
||||
uint32_t operator * () const
|
||||
{
|
||||
octet_iterator temp = it;
|
||||
return utf8::unchecked::next(temp);
|
||||
}
|
||||
bool operator == (const iterator& rhs) const
|
||||
{
|
||||
return (it == rhs.it);
|
||||
}
|
||||
bool operator != (const iterator& rhs) const
|
||||
{
|
||||
return !(operator == (rhs));
|
||||
}
|
||||
iterator& operator ++ ()
|
||||
{
|
||||
::std::advance(it, utf8::internal::sequence_length(it));
|
||||
return *this;
|
||||
}
|
||||
iterator operator ++ (int)
|
||||
{
|
||||
iterator temp = *this;
|
||||
::std::advance(it, utf8::internal::sequence_length(it));
|
||||
return temp;
|
||||
}
|
||||
iterator& operator -- ()
|
||||
{
|
||||
utf8::unchecked::prior(it);
|
||||
return *this;
|
||||
}
|
||||
iterator operator -- (int)
|
||||
{
|
||||
iterator temp = *this;
|
||||
utf8::unchecked::prior(it);
|
||||
return temp;
|
||||
}
|
||||
}; // class iterator
|
||||
|
||||
} // namespace utf8::unchecked
|
||||
} // namespace utf8
|
||||
|
||||
|
||||
#endif // header guard
|
||||
|
||||
Reference in New Issue
Block a user