GDevelop Core
Core library for developing platforms and tools compatible with GDevelop.
sole.h
1 
48 
49 #pragma once
50 #include <stdint.h>
51 #include <stdio.h> // for size_t; should be stddef.h instead; however, clang+archlinux fails when compiling it (@Travis-Ci)
52 #include <sys/types.h> // for uint32_t; should be stdint.h instead; however, GCC 5 on OSX fails when compiling it (See issue #11)
53 #include <functional>
54 #include <string>
55 
56 // public API
57 
58 namespace sole
59 {
60  // 128-bit basic UUID type that allows comparison and sorting.
61  // Use .str() for printing and .pretty() for pretty printing.
62  // Also, ostream friendly.
63  struct uuid
64  {
65  uint64_t ab;
66  uint64_t cd;
67 
68  bool operator==( const uuid &other ) const;
69  bool operator!=( const uuid &other ) const;
70  bool operator <( const uuid &other ) const;
71 
72  std::string base62() const;
73  std::string str() const;
74 
75  template<typename ostream>
76  inline friend ostream &operator<<( ostream &os, const uuid &self ) {
77  return os << self.str(), os;
78  }
79  };
80 
81  // Generators
82  uuid uuid4(); // UUID v4, pros: anonymous, fast; con: uuids "can clash"
83 
84  // Rebuilders
85  uuid rebuild( uint64_t ab, uint64_t cd );
86  uuid rebuild( const std::string &uustr );
87 }
88 
89 #ifdef _MSC_VER
90 #pragma warning(push)
91 #pragma warning(disable:4127)
92 #endif
93 
94 namespace std {
95  template<>
96  struct hash< sole::uuid > {
97  public:
98  // hash functor: hash uuid to size_t value by pseudorandomizing transform
99  size_t operator()( const sole::uuid &uuid ) const {
100  if( sizeof(size_t) > 4 ) {
101  return size_t( uuid.ab ^ uuid.cd );
102  } else {
103  uint64_t hash64 = uuid.ab ^ uuid.cd;
104  return size_t( uint32_t( hash64 >> 32 ) ^ uint32_t( hash64 ) );
105  }
106  }
107  };
108 }
109 
110 #ifdef _MSC_VER
111 #pragma warning(pop)
112 #endif
113 
114 // implementation
115 
116 #include <memory.h>
117 #include <stdint.h>
118 #include <stdio.h>
119 #include <time.h>
120 
121 #include <cstring>
122 #include <ctime>
123 
124 #include <iomanip>
125 #include <random>
126 #include <sstream>
127 #include <string>
128 #include <vector>
129 
130 #include <unistd.h>
131 
132 inline bool sole::uuid::operator==( const sole::uuid &other ) const {
133  return ab == other.ab && cd == other.cd;
134 }
135 inline bool sole::uuid::operator!=( const sole::uuid &other ) const {
136  return !operator==(other);
137 }
138 inline bool sole::uuid::operator<( const sole::uuid &other ) const {
139  if( ab < other.ab ) return true;
140  if( ab > other.ab ) return false;
141  if( cd < other.cd ) return true;
142  return false;
143 }
144 
145 namespace sole {
146 
147  inline std::string uuid::str() const {
148  std::stringstream ss;
149  ss << std::hex << std::nouppercase << std::setfill('0');
150 
151  uint32_t a = (ab >> 32);
152  uint32_t b = (ab & 0xFFFFFFFF);
153  uint32_t c = (cd >> 32);
154  uint32_t d = (cd & 0xFFFFFFFF);
155 
156  ss << std::setw(8) << (a) << '-';
157  ss << std::setw(4) << (b >> 16) << '-';
158  ss << std::setw(4) << (b & 0xFFFF) << '-';
159  ss << std::setw(4) << (c >> 16 ) << '-';
160  ss << std::setw(4) << (c & 0xFFFF);
161  ss << std::setw(8) << d;
162 
163  return ss.str();
164  }
165 
166  inline std::string uuid::base62() const {
167  int base62len = 10 + 26 + 26;
168  const char base62[] =
169  "0123456789"
170  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
171  "abcdefghijklmnopqrstuvwxyz";
172  char res[24], *end = &res[24]; *(--end) = '\0';
173  uint64_t rem, AB = ab, CD = cd;
174  do {
175  rem = CD % base62len;
176  *--end = base62[int(rem)];
177  CD /= base62len;
178  } while (CD > 0);
179  *--end = '-';
180  do {
181  rem = AB % base62len;
182  *--end = base62[int(rem)];
183  AB /= base62len;
184  } while (AB > 0);
185  return end;
186  }
187 
189  // UUID implementations
190 
191  inline uuid uuid4() {
192  static std::random_device rd;
193  static std::uniform_int_distribution<uint64_t> dist(0, (uint64_t)(~0));
194 
195  uuid my;
196 
197  my.ab = dist(rd);
198  my.cd = dist(rd);
199 
200  my.ab = (my.ab & 0xFFFFFFFFFFFF0FFFULL) | 0x0000000000004000ULL;
201  my.cd = (my.cd & 0x3FFFFFFFFFFFFFFFULL) | 0x8000000000000000ULL;
202 
203  return my;
204  }
205 
206  inline uuid rebuild( uint64_t ab, uint64_t cd ) {
207  uuid u;
208  u.ab = ab; u.cd = cd;
209  return u;
210  }
211 
212  inline uuid rebuild( const std::string &uustr ) {
213  char sep;
214  uint64_t a,b,c,d,e;
215  uuid u = { 0, 0 };
216  auto idx = uustr.find_first_of("-");
217  if( idx != std::string::npos ) {
218  // single separator, base62 notation
219  if( uustr.find_first_of("-",idx+1) == std::string::npos ) {
220  auto rebase62 = [&]( const char *input, size_t limit ) -> uint64_t {
221  int base62len = 10 + 26 + 26;
222  auto strpos = []( char ch ) -> size_t {
223  if( ch >= 'a' ) return ch - 'a' + 10 + 26;
224  if( ch >= 'A' ) return ch - 'A' + 10;
225  return ch - '0';
226  };
227  uint64_t res = strpos( input[0] );
228  for( size_t i = 1; i < limit; ++i )
229  res = base62len * res + strpos( input[i] );
230  return res;
231  };
232  u.ab = rebase62( &uustr[0], idx );
233  u.cd = rebase62( &uustr[idx+1], uustr.size() - (idx+1) );
234  }
235  // else classic hex notation
236  else {
237  std::stringstream ss( uustr );
238  if( ss >> std::hex >> a >> sep >> b >> sep >> c >> sep >> d >> sep >> e ) {
239  if( ss.eof() ) {
240  u.ab = (a << 32) | (b << 16) | c;
241  u.cd = (d << 48) | e;
242  }
243  }
244  }
245  }
246  return u;
247  }
248 
249 } // ::sole
Definition: sole.h:59
Definition: sole.h:64