utility.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #pragma once
  2. namespace nall {
  3. auto string::read(string_view filename) -> string {
  4. #if !defined(_WIN32)
  5. FILE* fp = fopen(filename, "rb");
  6. #else
  7. FILE* fp = _wfopen(utf16_t(filename), L"rb");
  8. #endif
  9. string result;
  10. if(!fp) return result;
  11. fseek(fp, 0, SEEK_END);
  12. int filesize = ftell(fp);
  13. if(filesize < 0) return fclose(fp), result;
  14. rewind(fp);
  15. result.resize(filesize);
  16. (void)fread(result.get(), 1, filesize, fp);
  17. return fclose(fp), result;
  18. }
  19. auto string::repeat(string_view pattern, uint times) -> string {
  20. string result;
  21. while(times--) result.append(pattern.data());
  22. return result;
  23. }
  24. auto string::fill(char fill) -> string& {
  25. memory::fill(get(), size(), fill);
  26. return *this;
  27. }
  28. auto string::hash() const -> uint {
  29. const char* p = data();
  30. uint length = size();
  31. uint result = 5381;
  32. while(length--) result = (result << 5) + result + *p++;
  33. return result;
  34. }
  35. auto string::remove(uint offset, uint length) -> string& {
  36. char* p = get();
  37. length = min(length, size());
  38. memory::move(p + offset, p + offset + length, size() - length);
  39. return resize(size() - length);
  40. }
  41. auto string::reverse() -> string& {
  42. char* p = get();
  43. uint length = size();
  44. uint pivot = length >> 1;
  45. for(int x = 0, y = length - 1; x < pivot && y >= 0; x++, y--) std::swap(p[x], p[y]);
  46. return *this;
  47. }
  48. //+length => insert/delete from start (right justify)
  49. //-length => insert/delete from end (left justify)
  50. auto string::size(int length, char fill) -> string& {
  51. uint size = this->size();
  52. if(size == length) return *this;
  53. bool right = length >= 0;
  54. length = abs(length);
  55. if(size < length) { //expand
  56. resize(length);
  57. char* p = get();
  58. uint displacement = length - size;
  59. if(right) memory::move(p + displacement, p, size);
  60. else p += size;
  61. while(displacement--) *p++ = fill;
  62. } else { //shrink
  63. char* p = get();
  64. uint displacement = size - length;
  65. if(right) memory::move(p, p + displacement, length);
  66. resize(length);
  67. }
  68. return *this;
  69. }
  70. auto slice(string_view self, int offset, int length) -> string {
  71. string result;
  72. if(offset < 0) offset = self.size() - abs(offset);
  73. if(offset >= 0 && offset < self.size()) {
  74. if(length < 0) length = self.size() - offset;
  75. if(length >= 0) {
  76. result.resize(length);
  77. memory::copy(result.get(), self.data() + offset, length);
  78. }
  79. }
  80. return result;
  81. }
  82. auto string::slice(int offset, int length) const -> string {
  83. return nall::slice(*this, offset, length);
  84. }
  85. template<typename T> auto fromInteger(char* result, T value) -> char* {
  86. bool negative = value < 0;
  87. if(!negative) value = -value; //negate positive integers to support eg INT_MIN
  88. char buffer[1 + sizeof(T) * 3];
  89. uint size = 0;
  90. do {
  91. int n = value % 10; //-0 to -9
  92. buffer[size++] = '0' - n; //'0' to '9'
  93. value /= 10;
  94. } while(value);
  95. if(negative) buffer[size++] = '-';
  96. for(int x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y];
  97. result[size] = 0;
  98. return result;
  99. }
  100. template<typename T> auto fromNatural(char* result, T value) -> char* {
  101. char buffer[1 + sizeof(T) * 3];
  102. uint size = 0;
  103. do {
  104. uint n = value % 10;
  105. buffer[size++] = '0' + n;
  106. value /= 10;
  107. } while(value);
  108. for(int x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y];
  109. result[size] = 0;
  110. return result;
  111. }
  112. //using sprintf is certainly not the most ideal method to convert
  113. //a double to a string ... but attempting to parse a double by
  114. //hand, digit-by-digit, results in subtle rounding errors.
  115. template<typename T> auto fromReal(char* result, T value) -> uint {
  116. char buffer[256];
  117. #ifdef _WIN32
  118. //Windows C-runtime does not support long double via sprintf()
  119. sprintf(buffer, "%f", (double)value);
  120. #else
  121. sprintf(buffer, "%Lf", (long double)value);
  122. #endif
  123. //remove excess 0's in fraction (2.500000 -> 2.5)
  124. for(char* p = buffer; *p; p++) {
  125. if(*p == '.') {
  126. char* p = buffer + strlen(buffer) - 1;
  127. while(*p == '0') {
  128. if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1.
  129. p--;
  130. }
  131. break;
  132. }
  133. }
  134. uint length = strlen(buffer);
  135. if(result) strcpy(result, buffer);
  136. return length + 1;
  137. }
  138. }