mirror of
https://github.com/zeldaret/tww.git
synced 2026-07-08 13:46:21 -04:00
std-vector equivalent
This commit is contained in:
+1
-1
@@ -920,7 +920,7 @@ config.libs = [
|
||||
[
|
||||
Object(Matching, "JSystem/JGadget/binary.cpp"),
|
||||
Object(Matching, "JSystem/JGadget/linklist.cpp"),
|
||||
Object(NonMatching, "JSystem/JGadget/std-vector.cpp"),
|
||||
Object(Equivalent, "JSystem/JGadget/std-vector.cpp"), # weak func order
|
||||
],
|
||||
),
|
||||
JSystemLib(
|
||||
|
||||
@@ -6,19 +6,35 @@
|
||||
namespace JGadget {
|
||||
template <typename T>
|
||||
struct TAllocator {
|
||||
// TODO: this constructor declaration needs to be removed in order to match TFunctionValue_composite's constructor
|
||||
// TODO: This explicit ctor needs to be removed in order to match TFunctionValue_composite's constructor
|
||||
// in functionvalue.cpp, and in order to get the @564 struct literal to appear in the .sbss section of that TU.
|
||||
// however, removing this declaration also causes that bss literal to appear in hundreds of other TUs it shouldn't.
|
||||
TAllocator();
|
||||
// However, removing this definition also causes that bss literal to appear in other TUs it shouldn't.
|
||||
// This seems related to the 16 1-byte weak bss symbols that appear in a ton of different TUs (@936 to @1036)
|
||||
// as this literal also has alignment 1 in the debug maps but alignment for in non-debug maps.
|
||||
// Specifically it's the JGadget::TAllocator<void*>() inside of TFunctionValueAttribute_refer that creates the literal.
|
||||
TAllocator() {}
|
||||
|
||||
// TODO
|
||||
void AllocateRaw(u32) {}
|
||||
void DeallocateRaw(void*) {}
|
||||
void allocate(u32, const void*) {}
|
||||
void deallocate(T*, u32) {}
|
||||
void destroy(T*) {}
|
||||
T* allocate(u32 count, const void *param_2) {
|
||||
return AllocateRaw(count * sizeof(T));
|
||||
}
|
||||
|
||||
/* 0x00 */ u8 _00;
|
||||
T* AllocateRaw(u32 size) {
|
||||
return (T*)operator new(size);
|
||||
}
|
||||
|
||||
void deallocate(T* mem, u32 size) {
|
||||
DeallocateRaw(mem);
|
||||
}
|
||||
|
||||
void DeallocateRaw(void* mem) {
|
||||
delete (T*)mem;
|
||||
}
|
||||
|
||||
void destroy(T* p) {
|
||||
// JUT_ASSERT(68, p!=0);
|
||||
}
|
||||
|
||||
/* 0x00 */ u8 mAllocator;
|
||||
};
|
||||
|
||||
typedef TAllocator<void*> TVoidAllocator;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#ifndef JGADGET_VECTOR_H
|
||||
#define JGADGET_VECTOR_H
|
||||
#ifndef _JSYSTEM_JGADGET_VECTOR_H
|
||||
#define _JSYSTEM_JGADGET_VECTOR_H
|
||||
|
||||
#include "JSystem/JGadget/allocator.h"
|
||||
#include "dolphin/types.h"
|
||||
#include "algorithm.h"
|
||||
#include "msl_memory.h"
|
||||
|
||||
namespace JGadget {
|
||||
namespace vector {
|
||||
@@ -12,69 +13,244 @@ typedef u32 (*ExtendFunc)(u32, u32, u32);
|
||||
|
||||
} // namespace vector
|
||||
|
||||
template <typename T, template <class> class Allocator>
|
||||
template <typename T, class Allocator = JGadget::TAllocator<T> /***/>
|
||||
struct TVector {
|
||||
// struct Destructed_deallocate_ {
|
||||
// ~Destructed_deallocate_(); // unused/inlined
|
||||
// };
|
||||
struct TDestructed_deallocate_ {
|
||||
TDestructed_deallocate_(JGadget::TAllocator<T>& alloc, T* pointer)
|
||||
{
|
||||
mAllocator = &alloc;
|
||||
mPointer = pointer;
|
||||
}
|
||||
|
||||
// TVector(u32, const T&, const Allocator<T>&);
|
||||
~TDestructed_deallocate_() { mAllocator->deallocate(mPointer, 0); }
|
||||
|
||||
// TVector(Allocator<T> alloc)
|
||||
// {
|
||||
// _00 = alloc._00;
|
||||
// _04 = nullptr;
|
||||
// mBegin = nullptr;
|
||||
// mEnd = nullptr;
|
||||
// mExtend = vector::extend_default;
|
||||
// }
|
||||
void set(T* p) { mPointer = p; }
|
||||
|
||||
~TVector();
|
||||
Allocator* mAllocator;
|
||||
T* mPointer;
|
||||
};
|
||||
|
||||
~TVector() {
|
||||
Confirm();
|
||||
clear();
|
||||
delete mBegin;
|
||||
}
|
||||
|
||||
// void insert(T*, u32, const T&);
|
||||
void insert(T* position, u32 count, T const& value)
|
||||
{
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
|
||||
void** v = Insert_raw(position, count); // insert `count` values before element at `position`
|
||||
|
||||
if (v != this->mEnd) {
|
||||
for (int i = 0; i != count; i++) {
|
||||
if (v) {
|
||||
*v = value;
|
||||
}
|
||||
v++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void** Insert_raw(T* position, u32 count)
|
||||
{
|
||||
// purpose: to make space for `count` many elements at the supplied location
|
||||
// returns: pointer to location for new items
|
||||
|
||||
T* const pFirst = position;
|
||||
|
||||
// JUT_DEBUG_ASSERT((mBegin<=pItFirst_)&&(pItFirst_<=mEnd), 0x1be);
|
||||
|
||||
// it's assumed the pointer is to something already in the vector, or pointing to the end
|
||||
|
||||
if (count == 0) {
|
||||
return position;
|
||||
}
|
||||
|
||||
// can we fit in the space already allocated?
|
||||
if (count + size() <= mCapacity) {
|
||||
|
||||
// get the theoretical new end
|
||||
void** newEnd = pFirst + count;
|
||||
|
||||
// if there exists items in the current vector past where we will insert these items
|
||||
// then we need to move them to be at the end of the vector
|
||||
if (newEnd < mEnd) {
|
||||
|
||||
// get a pointer to the `count` many values that need to be pushed to the end
|
||||
void** pOverwrittenValues = mEnd - count;
|
||||
|
||||
// copy `count` many values to the end of the vector
|
||||
std::uninitialized_copy(pOverwrittenValues, mEnd, mEnd);
|
||||
|
||||
// copy the remaining values that need to be shifted
|
||||
// copying backwards so we don't move a value into the range we're copying from, erasing data
|
||||
std::copy_backward(pFirst, pOverwrittenValues, mEnd);
|
||||
|
||||
// destroy everything from pFirst -> newEnd, this treats the inserted items as "uninitialized"
|
||||
DestroyElement_(pFirst, newEnd);
|
||||
|
||||
// increment count
|
||||
mEnd += count;
|
||||
|
||||
// return pointer to new items
|
||||
return pFirst;
|
||||
} else {
|
||||
// position + count >= mEnd
|
||||
// else our values that we want to add will write beyond the current mEnd
|
||||
|
||||
// copy the values that exist at our pointer to the newEnd, which is position + count, making room for our `count` many
|
||||
// items
|
||||
std::uninitialized_copy(pFirst, mEnd, newEnd);
|
||||
|
||||
// uninitialize the values that used to be there
|
||||
DestroyElement_(pFirst, mEnd);
|
||||
|
||||
// increment count
|
||||
mEnd += count;
|
||||
|
||||
// return pointer to new items
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
||||
// count + size() > mCapacity
|
||||
// we need more space
|
||||
|
||||
// figure out how much space we'll need
|
||||
u32 newSize = GetSize_extend_(count);
|
||||
|
||||
// allocate that space
|
||||
void** newDataPointer = mAllocator.allocate(newSize, 0);
|
||||
|
||||
// make sure that data was actually allocated
|
||||
if (!newDataPointer) {
|
||||
// return end pointer so we know not to actually assign any values
|
||||
return end();
|
||||
}
|
||||
|
||||
// this struct will deallocate the specified data pointer when destroyed
|
||||
// If we end up throwing an exception, it'll deallocate our new data pointer, no leaks!
|
||||
TDestructed_deallocate_ destructionDeallocator(mAllocator, newDataPointer);
|
||||
|
||||
// copy all the beginning of our data up to our pointer to the new data
|
||||
void** const endOfCopy = std::uninitialized_copy(mBegin, pFirst, newDataPointer);
|
||||
|
||||
// copy the rest of the data to fit at the end of our new data
|
||||
// this leaves a gap of `count` many items in our new data
|
||||
std::uninitialized_copy(pFirst, mEnd, endOfCopy + count);
|
||||
|
||||
// destroy all our current elements, the other elements should be living in the new data
|
||||
// and we're about to deallocate our
|
||||
DestroyElement_all_();
|
||||
|
||||
// everything should be set, so now we can deallocate our old data pointer
|
||||
// when this func exits
|
||||
destructionDeallocator.set(mBegin);
|
||||
|
||||
// set our new vector member variables
|
||||
mEnd = newDataPointer + (mEnd - mBegin + count);
|
||||
mBegin = newDataPointer;
|
||||
mCapacity = newSize;
|
||||
|
||||
// return where the gap of `count` many items lives
|
||||
return endOfCopy;
|
||||
}
|
||||
|
||||
void** insert(T* position, const T& value)
|
||||
{
|
||||
u32 posOffset = position - mBegin;
|
||||
// insert one value of `value` at `position`
|
||||
insert(position, 1, value);
|
||||
return mBegin + posOffset; // return pointer to new value at position
|
||||
}
|
||||
|
||||
void insert(T*, u32, const T&);
|
||||
void Insert_raw(T*, u32);
|
||||
void insert(T*, const T&);
|
||||
void assign(u32, const T&);
|
||||
void resize(u32, const T&);
|
||||
void Resize_raw(u32);
|
||||
void operator=(const TVector<T, Allocator>& rhs);
|
||||
void operator=(const TVector<T>& rhs);
|
||||
|
||||
inline u32 size() const {
|
||||
if (mBegin == NULL) {
|
||||
size_t GetSize_extend_(size_t count) const
|
||||
{
|
||||
u32 oldSize = size();
|
||||
u32 neededNewSpace = oldSize + count;
|
||||
u32 extendedSize = mExtend(capacity(), oldSize, count);
|
||||
|
||||
return neededNewSpace > extendedSize ? neededNewSpace : extendedSize;
|
||||
}
|
||||
|
||||
T* begin() { return mBegin; }
|
||||
T* const begin() const { return mBegin; }
|
||||
T* end() { return mEnd; }
|
||||
T* const end() const { return mEnd; }
|
||||
|
||||
size_t capacity() const { return mCapacity; }
|
||||
|
||||
inline size_t size() const
|
||||
{
|
||||
if (begin() == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((int)mEnd - (int)mBegin) / 4;
|
||||
}
|
||||
|
||||
void** begin() { return mBegin; }
|
||||
void** const begin() const { return mBegin; }
|
||||
void** end() { return mEnd; }
|
||||
void** const end() const { return mEnd; }
|
||||
void DestroyElement_(T* pFirst, T* pLast)
|
||||
{
|
||||
void** iter = pFirst;
|
||||
while (iter != pLast) {
|
||||
mAllocator.destroy(iter);
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
void DestroyElement_all_() { DestroyElement_(mBegin, mEnd); }
|
||||
|
||||
/* 0x04 */ u8 _00;
|
||||
/* 0x08 */ void** mBegin;
|
||||
/* 0x0C */ void** mEnd;
|
||||
/* 0x10 */ void** _0C;
|
||||
/* 0x14 */ vector::ExtendFunc mExtend;
|
||||
void Confirm() const {}
|
||||
|
||||
void clear() {
|
||||
erase(begin(), end());
|
||||
}
|
||||
T* erase(T* start, T* end) {
|
||||
T* ppvVar3 = std::copy(end, TVector::end(), start);
|
||||
DestroyElement_(ppvVar3, mEnd);
|
||||
mEnd = ppvVar3;
|
||||
return start;
|
||||
}
|
||||
|
||||
/* 0x00 */ Allocator mAllocator;
|
||||
/* 0x04 */ T* mBegin;
|
||||
/* 0x08 */ T* mEnd;
|
||||
/* 0x0C */ size_t mCapacity;
|
||||
/* 0x10 */ vector::ExtendFunc mExtend;
|
||||
};
|
||||
|
||||
struct TVector_pointer_void : TVector<void*, TAllocator> {
|
||||
TVector_pointer_void(const JGadget::TAllocator<void*>&);
|
||||
// clang-format off
|
||||
struct TVector_pointer_void : public TVector<void*, TAllocator<void*> > {
|
||||
TVector_pointer_void(const JGadget::TAllocator<void*>& allocator);
|
||||
TVector_pointer_void(u32, void* const&, const JGadget::TAllocator<void*>& allocator); // unused/inlined
|
||||
|
||||
~TVector_pointer_void();
|
||||
|
||||
void insert(void**, void* const&);
|
||||
void erase(void**, void**);
|
||||
void** erase(void**, void**);
|
||||
void** insert(void**, void* const&);
|
||||
|
||||
void clear() { erase(begin(), end()); }
|
||||
void push_back(const void*& ref) { insert(end(), (void* const&)ref); }
|
||||
void push_back(const void*& value) { insert(end(), (void* const&)value); }
|
||||
|
||||
/* 0x00 */ /* TVector */
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
template <typename T>
|
||||
struct TVector_pointer : TVector_pointer_void {
|
||||
TVector_pointer(const TAllocator<void*>& allocator) : TVector_pointer_void(allocator) {}
|
||||
~TVector_pointer() {}
|
||||
struct TVector_pointer : public TVector_pointer_void {
|
||||
TVector_pointer(const TAllocator<void*>& allocator)
|
||||
: TVector_pointer_void(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
~TVector_pointer() { }
|
||||
|
||||
const T* begin() const { return (const T*)TVector_pointer_void::begin(); }
|
||||
T* begin() { return (T*)TVector_pointer_void::begin(); }
|
||||
@@ -82,11 +258,144 @@ struct TVector_pointer : TVector_pointer_void {
|
||||
const T* end() const { return (const T*)TVector_pointer_void::end(); }
|
||||
T* end() { return (T*)TVector_pointer_void::end(); }
|
||||
|
||||
void push_back(const T& ref) {
|
||||
static_cast<TVector_pointer_void*>(this)->push_back((const void*&)ref);
|
||||
}
|
||||
void push_back(const T& value) { TVector_pointer_void::push_back((const void*&)value); }
|
||||
|
||||
/* 0x00 */ /* TVector_pointer_void */
|
||||
};
|
||||
|
||||
} // namespace JGadget
|
||||
// clang-format off
|
||||
typedef JGadget::TVector<void*, JGadget::TAllocator<void*> > TVPVBase;
|
||||
// clang-format on
|
||||
|
||||
#endif /* JGADGET_VECTOR_H */
|
||||
// template <>
|
||||
// void TVPVBase::insert(void** values, u32 count, void* const& defaultValue)
|
||||
// {
|
||||
// if (!count) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// void** v = Insert_raw(values, count);
|
||||
|
||||
// if (v != this->mEnd) {
|
||||
// for (int i = 0; i != count; i++) {
|
||||
// if (v) {
|
||||
// *v = defaultValue;
|
||||
// }
|
||||
// v++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* @note Address: 0x80027718
|
||||
* @note Size: 0x470
|
||||
*/
|
||||
template <>
|
||||
void** TVPVBase::Insert_raw(void** pItFirst, u32 count)
|
||||
{
|
||||
// purpose: to make space for `count` many elements at the supplied location
|
||||
// returns: pointer to location for new items
|
||||
|
||||
void** const pItFirst_ = pItFirst;
|
||||
|
||||
// JUT_DEBUG_ASSERT((mBegin<=pItFirst_)&&(pItFirst_<=mEnd), 0x1be);
|
||||
|
||||
// it's assumed the pointer is to something already in the vector, or pointing to the end
|
||||
|
||||
if (count == 0) {
|
||||
return pItFirst;
|
||||
}
|
||||
|
||||
// can we fit in the space already allocated?
|
||||
if (count + size() <= mCapacity) {
|
||||
|
||||
// get the theoretical new end
|
||||
void** newEnd = pItFirst_ + count;
|
||||
|
||||
// if there exists items in the current vector past where we will insert these items
|
||||
// then we need to move them to be at the end of the vector
|
||||
if (newEnd < mEnd) {
|
||||
|
||||
// get a pointer to the `count` many values that need to be pushed to the end
|
||||
void** pOverwrittenValues = mEnd - count;
|
||||
|
||||
// copy `count` many values to the end of the vector
|
||||
std::uninitialized_copy(pOverwrittenValues, mEnd, mEnd);
|
||||
|
||||
// copy the remaining values that need to be shifted
|
||||
// copying backwards so we don't move a value into the range we're copying from, erasing data
|
||||
std::copy_backward(pItFirst_, pOverwrittenValues, mEnd);
|
||||
|
||||
// destroy everything from pItFirst_ -> newEnd, this treats the inserted items as "uninitialized"
|
||||
DestroyElement_(pItFirst_, newEnd);
|
||||
|
||||
// increment count
|
||||
mEnd += count;
|
||||
|
||||
// return pointer to new items
|
||||
return pItFirst;
|
||||
} else {
|
||||
// pItFirst + count >= mEnd
|
||||
// else our values that we want to add will write beyond the current mEnd
|
||||
|
||||
// copy the values that exist at our pointer to the newEnd, which is pItFirst + count, making room for our `count` many
|
||||
// items
|
||||
std::uninitialized_copy(pItFirst_, mEnd, newEnd);
|
||||
|
||||
// uninitialize the values that used to be there
|
||||
DestroyElement_(pItFirst_, mEnd);
|
||||
|
||||
// increment count
|
||||
mEnd += count;
|
||||
|
||||
// return pointer to new items
|
||||
return pItFirst;
|
||||
}
|
||||
}
|
||||
|
||||
// count + size() > mCapacity
|
||||
// we need more space
|
||||
|
||||
// figure out how much space we'll need
|
||||
u32 newSize = GetSize_extend_(count);
|
||||
|
||||
// allocate that space
|
||||
void** newDataPointer = mAllocator.allocate(newSize, 0);
|
||||
|
||||
// make sure that data was actually allocated
|
||||
if (!newDataPointer) {
|
||||
// return end pointer?
|
||||
return end();
|
||||
}
|
||||
|
||||
// this struct will deallocate the specified data pointer when destroyed
|
||||
// If we end up throwing an exception, it'll deallocate our new data pointer, no leaks!
|
||||
TDestructed_deallocate_ destructionDeallocator(mAllocator, newDataPointer);
|
||||
|
||||
// copy all the beginning of our data up to our pointer to the new data
|
||||
void** const endOfCopy = std::uninitialized_copy(mBegin, pItFirst_, newDataPointer);
|
||||
|
||||
// copy the rest of the data to fit at the end of our new data
|
||||
// this leaves a gap of `count` many items in our new data
|
||||
std::uninitialized_copy(pItFirst_, mEnd, endOfCopy + count);
|
||||
|
||||
// destroy all our current elements, the other elements should be living in the new data
|
||||
// and we're about to deallocate our
|
||||
DestroyElement_all_();
|
||||
|
||||
// everything should be set, so now we can deallocate our old data pointer
|
||||
// when this func exits
|
||||
destructionDeallocator.set(mBegin);
|
||||
|
||||
// set our new vector member variables
|
||||
mEnd = newDataPointer + (mEnd - mBegin + count);
|
||||
mBegin = newDataPointer;
|
||||
mCapacity = newSize;
|
||||
|
||||
// return where the gap of `count` many items lives
|
||||
return endOfCopy;
|
||||
}
|
||||
|
||||
} // namespace JGadget
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "dolphin/types.h"
|
||||
|
||||
namespace JGadget {
|
||||
|
||||
|
||||
/* 802BFF14-802BFF1C .text extend_default__Q27JGadget6vectorFUlUlUl */
|
||||
u32 vector::extend_default(u32, u32 param_2, u32) {
|
||||
return param_2 * 2;
|
||||
@@ -15,26 +15,24 @@ u32 vector::extend_default(u32, u32 param_2, u32) {
|
||||
|
||||
/* 802BFF1C-802BFF48 .text __ct__Q27JGadget20TVector_pointer_voidFRCQ27JGadget14TAllocator<Pv> */
|
||||
TVector_pointer_void::TVector_pointer_void(const TAllocator<void*>& allocator) {
|
||||
_00 = allocator._00;
|
||||
mAllocator = allocator;
|
||||
mBegin = NULL;
|
||||
mEnd = mBegin;
|
||||
_0C = NULL;
|
||||
mCapacity = 0;
|
||||
mExtend = vector::extend_default;
|
||||
}
|
||||
|
||||
/* 802BFF48-802BFFF0 .text __dt__Q27JGadget20TVector_pointer_voidFv */
|
||||
TVector_pointer_void::~TVector_pointer_void() {
|
||||
/* Nonmatching */
|
||||
}
|
||||
TVector_pointer_void::~TVector_pointer_void() {}
|
||||
|
||||
/* 802BFFF0-802C0010 .text insert__Q27JGadget20TVector_pointer_voidFPPvRCPv */
|
||||
void TVector_pointer_void::insert(void**, void* const&) {
|
||||
/* Nonmatching */
|
||||
void** TVector_pointer_void::insert(void** position, void* const& value) {
|
||||
return TVector<void*>::insert(position, value);
|
||||
}
|
||||
|
||||
/* 802C0010-802C0068 .text erase__Q27JGadget20TVector_pointer_voidFPPvPPv */
|
||||
void TVector_pointer_void::erase(void**, void**) {
|
||||
/* Nonmatching */
|
||||
void** TVector_pointer_void::erase(void** start, void** end) {
|
||||
return TVector<void*>::erase(start, end);
|
||||
}
|
||||
|
||||
// /* 802C0068-802C00D8 .text insert__Q27JGadget38TVector<Pv,Q27JGadget14TAllocator<Pv>>FPPvUlRCPv */
|
||||
|
||||
@@ -1,9 +1,29 @@
|
||||
#ifndef MSL_ALGORITHM_H_
|
||||
#define MSL_ALGORITHM_H_
|
||||
|
||||
#include <iterator.h>
|
||||
|
||||
namespace std {
|
||||
template <class ForwardIterator, class T>
|
||||
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& val);
|
||||
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& val) {
|
||||
typedef typename iterator_traits<ForwardIterator>::difference_type difference_type;
|
||||
difference_type len = std::distance(first, last);
|
||||
|
||||
while (len > 0) {
|
||||
ForwardIterator i = first;
|
||||
difference_type step = len / 2;
|
||||
std::advance(i, step);
|
||||
|
||||
if (*i < val) {
|
||||
first = ++i;
|
||||
len -= step + 1;
|
||||
} else {
|
||||
len = step;
|
||||
}
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class ForwardIterator, class T>
|
||||
ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& val);
|
||||
@@ -38,11 +58,62 @@ void __fill(ForwardIt first, ForwardIt last, const T& value, std::random_access_
|
||||
*/
|
||||
|
||||
template<class ForwardIt, class T>
|
||||
void fill(ForwardIt first, ForwardIt last, const T& value) {
|
||||
inline void fill(ForwardIt first, ForwardIt last, const T& value) {
|
||||
for (; first != last; ++first){
|
||||
*first = value;
|
||||
}
|
||||
}
|
||||
|
||||
template<class InputIt, class OutputIt>
|
||||
inline OutputIt copy(InputIt first, InputIt last,
|
||||
OutputIt d_first) {
|
||||
for (; first < last; ++first, ++d_first) {
|
||||
*d_first = *first;
|
||||
}
|
||||
return d_first;
|
||||
}
|
||||
|
||||
template <class BidirectionalIterator1, class BidirectionalIterator2>
|
||||
inline BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result) {
|
||||
while (last != first)
|
||||
*--result = *--last;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, bool A>
|
||||
struct __copy_backward
|
||||
{
|
||||
static T* copy_backward(T* first, T* last, T* result)
|
||||
{
|
||||
while (last > first)
|
||||
*--result = *--last;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct __copy_backward<T, true>
|
||||
{
|
||||
static T* copy_backward(T* first, T* last, T* result)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
size_t n = static_cast<size_t>(last - first);
|
||||
result -= n;
|
||||
memmove(result, first, n*sizeof(T));
|
||||
return result;
|
||||
#else
|
||||
while (last > first)
|
||||
*--result = *--last;
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline T* copy_backward(T* first, T* last, T* result) {
|
||||
return __copy_backward<T, true>::copy_backward(first, last, result);
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
#ifndef ITERATOR_H
|
||||
#define ITERATOR_H
|
||||
#ifndef MSL_ITERATOR_H_
|
||||
#define MSL_ITERATOR_H_
|
||||
|
||||
#include "stddef.h"
|
||||
|
||||
namespace std {
|
||||
struct input_iterator_tag {};
|
||||
struct output_iterator_tag {};
|
||||
struct forward_iterator_tag : public input_iterator_tag {};
|
||||
struct bidirectional_iterator_tag : public forward_iterator_tag {};
|
||||
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
|
||||
|
||||
template <class Iterator>
|
||||
struct iterator_traits {
|
||||
typedef typename Iterator::difference_type difference_type;
|
||||
typedef typename Iterator::value_type value_type;
|
||||
typedef typename Iterator::pointer pointer;
|
||||
typedef typename Iterator::reference reference;
|
||||
typedef typename Iterator::iterator_category iterator_category;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct iterator_traits<T*> {
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
typedef random_access_iterator_tag iterator_category;
|
||||
};
|
||||
|
||||
template <class InputIterator, class Distance>
|
||||
inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
|
||||
for (; n > 0; --n)
|
||||
++i;
|
||||
}
|
||||
|
||||
template <class BidirectionalIterator, class Distance>
|
||||
inline void __advance(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag) {
|
||||
if (n >= 0)
|
||||
for (; n > 0; --n)
|
||||
++i;
|
||||
else
|
||||
for (; n < 0; ++n)
|
||||
--i;
|
||||
}
|
||||
|
||||
template <class RandomAccessIterator, class Distance>
|
||||
inline void __advance(RandomAccessIterator& i, Distance n, random_access_iterator_tag) {
|
||||
i += n;
|
||||
}
|
||||
|
||||
template <class InputIterator, class Distance>
|
||||
inline void advance(InputIterator& i, Distance n) {
|
||||
__advance(i, n, typename iterator_traits<InputIterator>::iterator_category());
|
||||
}
|
||||
|
||||
// TODO: combine this with above later
|
||||
template <class InputIt, class Distance>
|
||||
inline void advance_fake(InputIt& it, Distance n) {
|
||||
while (n > 0) {
|
||||
--n;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
inline typename iterator_traits<InputIterator>::difference_type
|
||||
__distance(InputIterator first, InputIterator last, input_iterator_tag) {
|
||||
typename iterator_traits<InputIterator>::difference_type result = 0;
|
||||
for (; first != last; ++first)
|
||||
++result;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class RandomAccessIterator>
|
||||
inline typename iterator_traits<RandomAccessIterator>::difference_type
|
||||
__distance(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag) {
|
||||
return last - first;
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
inline typename iterator_traits<InputIterator>::difference_type distance(InputIterator first,
|
||||
InputIterator last) {
|
||||
return __distance(first, last, typename iterator_traits<InputIterator>::iterator_category());
|
||||
}
|
||||
|
||||
// This needs to be defined with gcc concepts or something similar. Workaround.
|
||||
template <class InputIt, class Distance>
|
||||
inline void advance_pointer(InputIt& it, Distance n) {
|
||||
it += n;
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* ITERATOR_H */
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef MSL_MEMORY_H
|
||||
#define MSL_MEMORY_H
|
||||
#ifndef MSL_MEMORY_H_
|
||||
#define MSL_MEMORY_H_
|
||||
|
||||
#include "stddef.h"
|
||||
|
||||
namespace std {
|
||||
|
||||
template<class ForwardIt, class Size, class T>
|
||||
inline ForwardIt uninitialized_fill_n(ForwardIt first, Size count, const T& value) {
|
||||
for (; count--; ++first) {
|
||||
if (first != NULL) {
|
||||
*first = value;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template<class InputIterator, class ForwardIterator>
|
||||
inline ForwardIterator __uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result) {
|
||||
ForwardIterator __save = result;
|
||||
|
||||
for (; first != last; ++first, ++result) {
|
||||
*result = *first;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, bool A, bool B>
|
||||
struct __uninitialized_copy_helper {
|
||||
static T* uninitialized_copy(T* first, T* last, T* result) {
|
||||
return __uninitialized_copy(first, last, result);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct __uninitialized_copy_helper<T, true, false>
|
||||
{
|
||||
static T* uninitialized_copy(T* first, T* last, T* result)
|
||||
{
|
||||
for (; first < last; ++result, ++first)
|
||||
*result = *first;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline T* uninitialized_copy(T* first, T* last, T* result) {
|
||||
return __uninitialized_copy_helper<T, true, false>::uninitialized_copy(first, last, result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* MSL_MEMORY_H */
|
||||
Reference in New Issue
Block a user