#pragma once #include #include namespace nall::memory { template inline auto allocate(uint size) -> T*; template inline auto allocate(uint size, const T& value) -> T*; template inline auto resize(void* target, uint size) -> T*; inline auto free(void* target) -> void; template inline auto compare(const void* target, uint capacity, const void* source, uint size) -> int; template inline auto compare(const void* target, const void* source, uint size) -> int; template inline auto icompare(const void* target, uint capacity, const void* source, uint size) -> int; template inline auto icompare(const void* target, const void* source, uint size) -> int; template inline auto copy(void* target, uint capacity, const void* source, uint size) -> T*; template inline auto copy(void* target, const void* source, uint size) -> T*; template inline auto move(void* target, uint capacity, const void* source, uint size) -> T*; template inline auto move(void* target, const void* source, uint size) -> T*; template inline auto fill(void* target, uint capacity, const T& value = {}) -> T*; template inline auto assign(T* target) -> void {} template inline auto assign(T* target, const U& value, P&&... p) -> void; template inline auto readl(const void* source) -> T; template inline auto readm(const void* source) -> T; template inline auto writel(void* target, T data) -> void; template inline auto writem(void* target, T data) -> void; } namespace nall::memory { //implementation notes: //memcmp, memcpy, memmove have terrible performance on small block sizes (FreeBSD 10.0-amd64) //as this library is used extensively by nall/string, and most strings tend to be small, //this library hand-codes these functions instead. surprisingly, it's a substantial speedup template auto allocate(uint size) -> T* { return (T*)malloc(size * sizeof(T)); } template auto allocate(uint size, const T& value) -> T* { auto result = allocate(size); if(result) fill(result, size, value); return result; } template auto resize(void* target, uint size) -> T* { return (T*)realloc(target, size * sizeof(T)); } auto free(void* target) -> void { ::free(target); } template auto compare(const void* target, uint capacity, const void* source, uint size) -> int { auto t = (uint8_t*)target; auto s = (uint8_t*)source; auto l = min(capacity, size) * sizeof(T); while(l--) { auto x = *t++; auto y = *s++; if(x != y) return x - y; } if(capacity == size) return 0; return -(capacity < size); } template auto compare(const void* target, const void* source, uint size) -> int { return compare(target, size, source, size); } template auto icompare(const void* target, uint capacity, const void* source, uint size) -> int { auto t = (uint8_t*)target; auto s = (uint8_t*)source; auto l = min(capacity, size) * sizeof(T); while(l--) { auto x = *t++; auto y = *s++; if(x - 'A' < 26) x += 32; if(y - 'A' < 26) y += 32; if(x != y) return x - y; } return -(capacity < size); } template auto icompare(const void* target, const void* source, uint size) -> int { return icompare(target, size, source, size); } template auto copy(void* target, uint capacity, const void* source, uint size) -> T* { auto t = (uint8_t*)target; auto s = (uint8_t*)source; auto l = min(capacity, size) * sizeof(T); while(l--) *t++ = *s++; return (T*)target; } template auto copy(void* target, const void* source, uint size) -> T* { return copy(target, size, source, size); } template auto move(void* target, uint capacity, const void* source, uint size) -> T* { auto t = (uint8_t*)target; auto s = (uint8_t*)source; auto l = min(capacity, size) * sizeof(T); if(t < s) { while(l--) *t++ = *s++; } else { t += l; s += l; while(l--) *--t = *--s; } return (T*)target; } template auto move(void* target, const void* source, uint size) -> T* { return move(target, size, source, size); } template auto fill(void* target, uint capacity, const T& value) -> T* { auto t = (T*)target; while(capacity--) *t++ = value; return (T*)target; } template auto assign(T* target, const U& value, P&&... p) -> void { *target++ = value; assign(target, forward

(p)...); } template auto readl(const void* source) -> T { auto p = (const uint8_t*)source; T data = 0; for(uint n = 0; n < size; n++) data |= T(*p++) << n * 8; return data; } template auto readm(const void* source) -> T { auto p = (const uint8_t*)source; T data = 0; for(int n = size - 1; n >= 0; n--) data |= T(*p++) << n * 8; return data; } template auto writel(void* target, T data) -> void { auto p = (uint8_t*)target; for(uint n = 0; n < size; n++) *p++ = data >> n * 8; } template auto writem(void* target, T data) -> void { auto p = (uint8_t*)target; for(int n = size - 1; n >= 0; n--) *p++ = data >> n * 8; } }