1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
#pragma once
#include <nall/algorithm.hpp>
#include <nall/stdint.hpp>
namespace nall { namespace memory {
inline auto allocate(uint size) -> void*;
inline auto allocate(uint size, uint8_t data) -> void*;
inline auto resize(void* target, uint size) -> void*;
inline auto free(void* target) -> void;
inline auto compare(const void* target, uint capacity, const void* source, uint size) -> int;
inline auto compare(const void* target, const void* source, uint size) -> int;
inline auto icompare(const void* target, uint capacity, const void* source, uint size) -> int;
inline auto icompare(const void* target, const void* source, uint size) -> int;
inline auto copy(void* target, uint capacity, const void* source, uint size) -> void*;
inline auto copy(void* target, const void* source, uint size) -> void*;
inline auto move(void* target, uint capacity, const void* source, uint size) -> void*;
inline auto move(void* target, const void* source, uint size) -> void*;
inline auto fill(void* target, uint capacity, uint8_t data = 0x00) -> void*;
template<typename T> inline auto assign(T* target) -> void {}
template<typename T, typename U, typename... P> inline auto assign(T* target, const U& value, P&&... p) -> void;
template<uint size, typename T = uint64_t> inline auto readl(const void* source) -> T;
template<uint size, typename T = uint64_t> inline auto readm(const void* source) -> T;
template<uint size, typename T = uint64_t> inline auto writel(void* target, T data) -> void;
template<uint size, typename T = uint64_t> inline auto writem(void* target, T data) -> void;
}}
namespace nall {
//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
auto memory::allocate(uint size) -> void* {
return malloc(size);
}
auto memory::allocate(uint size, uint8_t data) -> void* {
auto result = malloc(size);
if(result) fill(result, size, data);
return result;
}
auto memory::resize(void* target, uint size) -> void* {
return realloc(target, size);
}
auto memory::free(void* target) -> void {
::free(target);
}
auto memory::compare(const void* target, uint capacity, const void* source, uint size) -> int {
auto t = (int8_t*)target;
auto s = (int8_t*)source;
auto l = min(capacity, size);
while(l--) {
auto x = *t++;
auto y = *s++;
if(x != y) return x - y;
}
return 0;
}
auto memory::compare(const void* target, const void* source, uint size) -> int {
return compare(target, size, source, size);
}
auto memory::icompare(const void* target, uint capacity, const void* source, uint size) -> int {
auto t = (int8_t*)target;
auto s = (int8_t*)source;
auto l = min(capacity, size);
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 0;
}
auto memory::icompare(const void* target, const void* source, uint size) -> int {
return icompare(target, size, source, size);
}
auto memory::copy(void* target, uint capacity, const void* source, uint size) -> void* {
auto t = (uint8_t*)target;
auto s = (uint8_t*)source;
auto l = min(capacity, size);
while(l--) *t++ = *s++;
return target;
}
auto memory::copy(void* target, const void* source, uint size) -> void* {
return copy(target, size, source, size);
}
auto memory::move(void* target, uint capacity, const void* source, uint size) -> void* {
auto t = (uint8_t*)target;
auto s = (uint8_t*)source;
auto l = min(capacity, size);
if(t < s) {
while(l--) *t++ = *s++;
} else {
t += l;
s += l;
while(l--) *--t = *--s;
}
return target;
}
auto memory::move(void* target, const void* source, uint size) -> void* {
return move(target, size, source, size);
}
auto memory::fill(void* target, uint capacity, uint8_t data) -> void* {
auto t = (uint8_t*)target;
while(capacity--) *t++ = data;
return target;
}
template<typename T, typename U, typename... P>
auto memory::assign(T* target, const U& value, P&&... p) -> void {
*target++ = value;
assign(target, forward<P>(p)...);
}
template<uint size, typename T> auto memory::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<uint size, typename T> auto memory::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<uint size, typename T> auto memory::writel(void* target, T data) -> void {
auto p = (uint8_t*)target;
for(uint n = 0; n < size; n++) *p++ = data >> n * 8;
}
template<uint size, typename T> auto memory::writem(void* target, T data) -> void {
auto p = (uint8_t*)target;
for(int n = size - 1; n >= 0; n--) *p++ = data >> n * 8;
}
}
|