memory.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #pragma once
  2. #include <nall/algorithm.hpp>
  3. #include <nall/stdint.hpp>
  4. namespace nall::memory {
  5. template<typename T = uint8_t> auto allocate(uint size) -> T*;
  6. template<typename T = uint8_t> auto allocate(uint size, const T& value) -> T*;
  7. template<typename T = uint8_t> auto resize(void* target, uint size) -> T*;
  8. auto free(void* target) -> void;
  9. template<typename T = uint8_t> auto compare(const void* target, uint capacity, const void* source, uint size) -> int;
  10. template<typename T = uint8_t> auto compare(const void* target, const void* source, uint size) -> int;
  11. template<typename T = uint8_t> auto icompare(const void* target, uint capacity, const void* source, uint size) -> int;
  12. template<typename T = uint8_t> auto icompare(const void* target, const void* source, uint size) -> int;
  13. template<typename T = uint8_t> auto copy(void* target, uint capacity, const void* source, uint size) -> T*;
  14. template<typename T = uint8_t> auto copy(void* target, const void* source, uint size) -> T*;
  15. template<typename T = uint8_t> auto move(void* target, uint capacity, const void* source, uint size) -> T*;
  16. template<typename T = uint8_t> auto move(void* target, const void* source, uint size) -> T*;
  17. template<typename T = uint8_t> auto fill(void* target, uint capacity, const T& value = {}) -> T*;
  18. template<typename T> auto assign(T* target) -> void {}
  19. template<typename T, typename U, typename... P> auto assign(T* target, const U& value, P&&... p) -> void;
  20. template<uint size, typename T = uint64_t> auto readl(const void* source) -> T;
  21. template<uint size, typename T = uint64_t> auto readm(const void* source) -> T;
  22. template<uint size, typename T = uint64_t> auto writel(void* target, T data) -> void;
  23. template<uint size, typename T = uint64_t> auto writem(void* target, T data) -> void;
  24. }
  25. namespace nall::memory {
  26. //implementation notes:
  27. //memcmp, memcpy, memmove have terrible performance on small block sizes (FreeBSD 10.0-amd64)
  28. //as this library is used extensively by nall/string, and most strings tend to be small,
  29. //this library hand-codes these functions instead. surprisingly, it's a substantial speedup
  30. template<typename T> auto allocate(uint size) -> T* {
  31. return (T*)malloc(size * sizeof(T));
  32. }
  33. template<typename T> auto allocate(uint size, const T& value) -> T* {
  34. auto result = allocate<T>(size);
  35. if(result) fill<T>(result, size, value);
  36. return result;
  37. }
  38. template<typename T> auto resize(void* target, uint size) -> T* {
  39. return (T*)realloc(target, size * sizeof(T));
  40. }
  41. inline auto free(void* target) -> void {
  42. ::free(target);
  43. }
  44. template<typename T> auto compare(const void* target, uint capacity, const void* source, uint size) -> int {
  45. auto t = (uint8_t*)target;
  46. auto s = (uint8_t*)source;
  47. auto l = min(capacity, size) * sizeof(T);
  48. while(l--) {
  49. auto x = *t++;
  50. auto y = *s++;
  51. if(x != y) return x - y;
  52. }
  53. if(capacity == size) return 0;
  54. return -(capacity < size);
  55. }
  56. template<typename T> auto compare(const void* target, const void* source, uint size) -> int {
  57. return compare<T>(target, size, source, size);
  58. }
  59. template<typename T> auto icompare(const void* target, uint capacity, const void* source, uint size) -> int {
  60. auto t = (uint8_t*)target;
  61. auto s = (uint8_t*)source;
  62. auto l = min(capacity, size) * sizeof(T);
  63. while(l--) {
  64. auto x = *t++;
  65. auto y = *s++;
  66. if(x - 'A' < 26) x += 32;
  67. if(y - 'A' < 26) y += 32;
  68. if(x != y) return x - y;
  69. }
  70. return -(capacity < size);
  71. }
  72. template<typename T> auto icompare(const void* target, const void* source, uint size) -> int {
  73. return icompare<T>(target, size, source, size);
  74. }
  75. template<typename T> auto copy(void* target, uint capacity, const void* source, uint size) -> T* {
  76. auto t = (uint8_t*)target;
  77. auto s = (uint8_t*)source;
  78. auto l = min(capacity, size) * sizeof(T);
  79. while(l--) *t++ = *s++;
  80. return (T*)target;
  81. }
  82. template<typename T> auto copy(void* target, const void* source, uint size) -> T* {
  83. return copy<T>(target, size, source, size);
  84. }
  85. template<typename T> auto move(void* target, uint capacity, const void* source, uint size) -> T* {
  86. auto t = (uint8_t*)target;
  87. auto s = (uint8_t*)source;
  88. auto l = min(capacity, size) * sizeof(T);
  89. if(t < s) {
  90. while(l--) *t++ = *s++;
  91. } else {
  92. t += l;
  93. s += l;
  94. while(l--) *--t = *--s;
  95. }
  96. return (T*)target;
  97. }
  98. template<typename T> auto move(void* target, const void* source, uint size) -> T* {
  99. return move<T>(target, size, source, size);
  100. }
  101. template<typename T> auto fill(void* target, uint capacity, const T& value) -> T* {
  102. auto t = (T*)target;
  103. while(capacity--) *t++ = value;
  104. return (T*)target;
  105. }
  106. template<typename T, typename U, typename... P> auto assign(T* target, const U& value, P&&... p) -> void {
  107. *target++ = value;
  108. assign(target, forward<P>(p)...);
  109. }
  110. template<uint size, typename T> auto readl(const void* source) -> T {
  111. auto p = (const uint8_t*)source;
  112. T data = 0;
  113. for(uint n = 0; n < size; n++) data |= T(*p++) << n * 8;
  114. return data;
  115. }
  116. template<uint size, typename T> auto readm(const void* source) -> T {
  117. auto p = (const uint8_t*)source;
  118. T data = 0;
  119. for(int n = size - 1; n >= 0; n--) data |= T(*p++) << n * 8;
  120. return data;
  121. }
  122. template<uint size, typename T> auto writel(void* target, T data) -> void {
  123. auto p = (uint8_t*)target;
  124. for(uint n = 0; n < size; n++) *p++ = data >> n * 8;
  125. }
  126. template<uint size, typename T> auto writem(void* target, T data) -> void {
  127. auto p = (uint8_t*)target;
  128. for(int n = size - 1; n >= 0; n--) *p++ = data >> n * 8;
  129. }
  130. }