File: utility.hpp

package info (click to toggle)
higan 098-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 11,904 kB
  • ctags: 13,286
  • sloc: cpp: 108,285; ansic: 778; makefile: 32; sh: 18
file content (158 lines) | stat: -rw-r--r-- 3,829 bytes parent folder | download
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
#pragma once

namespace nall {

auto string::read(rstring filename) -> string {
  #if !defined(_WIN32)
  FILE* fp = fopen(filename, "rb");
  #else
  FILE* fp = _wfopen(utf16_t(filename), L"rb");
  #endif

  string result;
  if(!fp) return result;

  fseek(fp, 0, SEEK_END);
  int filesize = ftell(fp);
  if(filesize < 0) return fclose(fp), result;

  rewind(fp);
  result.resize(filesize);
  auto unused = fread(result.get(), 1, filesize, fp);
  return fclose(fp), result;
}

auto string::repeat(rstring pattern, uint times) -> string {
  string result;
  while(times--) result.append(pattern.data());
  return result;
}

auto string::fill(char fill) -> string& {
  memory::fill(get(), size(), fill);
  return *this;
}

auto string::hash() const -> unsigned {
  const char* p = data();
  uint length = size();
  uint result = 5381;
  while(length--) result = (result << 5) + result + *p++;
  return result;
}

auto string::remove(uint offset, uint length) -> string& {
  char* p = get();
  length = min(length, size());
  memory::move(p + offset, p + offset + length, size() - length);
  return resize(size() - length);
}

auto string::reverse() -> string& {
  char* p = get();
  uint length = size();
  uint pivot = length >> 1;
  for(int x = 0, y = length - 1; x < pivot && y >= 0; x++, y--) std::swap(p[x], p[y]);
  return *this;
}

//+length => insert/delete from start (right justify)
//-length => insert/delete from end (left justify)
auto string::size(int length, char fill) -> string& {
  uint size = this->size();
  if(size == length) return *this;

  bool right = length >= 0;
  length = abs(length);

  if(size < length) {  //expand
    resize(length);
    char* p = get();
    uint displacement = length - size;
    if(right) memory::move(p + displacement, p, size);
    else p += size;
    while(displacement--) *p++ = fill;
  } else {  //shrink
    char* p = get();
    uint displacement = size - length;
    if(right) memory::move(p, p + displacement, length);
    resize(length);
  }

  return *this;
}

auto slice(rstring self, int offset, int length) -> string {
  string result;
  if(offset < self.size()) {
    if(length < 0) length = self.size() - offset;
    result.resize(length);
    memory::copy(result.get(), self.data() + offset, length);
  }
  return result;
}

auto integer(char* result, intmax value) -> char* {
  bool negative = value < 0;
  if(negative) value = -value;

  char buffer[64];
  uint size = 0;

  do {
    uint n = value % 10;
    buffer[size++] = '0' + n;
    value /= 10;
  } while(value);
  if(negative) buffer[size++] = '-';

  for(int x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y];
  result[size] = 0;
  return result;
}

auto natural(char* result, uintmax value) -> char* {
  char buffer[64];
  uint size = 0;

  do {
    uint n = value % 10;
    buffer[size++] = '0' + n;
    value /= 10;
  } while(value);

  for(int x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y];
  result[size] = 0;
  return result;
}

//using sprintf is certainly not the most ideal method to convert
//a double to a string ... but attempting to parse a double by
//hand, digit-by-digit, results in subtle rounding errors.
auto real(char* result, long double value) -> uint {
  char buffer[256];
  #ifdef _WIN32
  //Windows C-runtime does not support long double via sprintf()
  sprintf(buffer, "%f", (double)value);
  #else
  sprintf(buffer, "%Lf", value);
  #endif

  //remove excess 0's in fraction (2.500000 -> 2.5)
  for(char* p = buffer; *p; p++) {
    if(*p == '.') {
      char* p = buffer + strlen(buffer) - 1;
      while(*p == '0') {
        if(*(p - 1) != '.') *p = 0;  //... but not for eg 1.0 -> 1.
        p--;
      }
      break;
    }
  }

  uint length = strlen(buffer);
  if(result) strcpy(result, buffer);
  return length + 1;
}

}