1 module appbase.utils.utility; 2 3 import std.file; 4 import std.path; 5 import std..string; 6 import std.conv; 7 import std.datetime; 8 import std.array; 9 import std.uuid : randomUUID; 10 import std.random; 11 import std.digest : toHexString; 12 import std.digest.md : MD5Digest; 13 import std.digest.ripemd : RIPEMD160Digest; 14 import std.regex; 15 import std.algorithm; 16 import std.traits : Unqual; 17 import std.zlib; 18 19 string getExePath() 20 { 21 return dirName(thisExePath); 22 } 23 24 string getExeName() 25 { 26 return baseName(thisExePath); 27 } 28 29 string genUuid(const bool hasSeparator = false) 30 { 31 string str = randomUUID.toString; 32 return hasSeparator ? str : str.replace("-", "").toUpper(); 33 } 34 35 string randomAlphanumeric(const size_t length) 36 { 37 if (length <= 0) 38 { 39 return string.init; 40 } 41 42 immutable char[] chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 43 char[] result = new char[length]; 44 45 for (size_t i = 0; i < length; i++) 46 { 47 result[i] = chars[rnd.next!byte(1, chars.length) - 1]; 48 } 49 50 return cast(immutable char[])result; 51 } 52 53 string MD5(scope const(void[])[] src...) 54 { 55 auto md5 = new MD5Digest(); 56 ubyte[] hash = md5.digest(src); 57 58 return hash.toHexString!(LetterCase.upper); 59 } 60 61 string RIPEMD160(scope const(void[])[] src...) 62 { 63 auto md = new RIPEMD160Digest(); 64 ubyte[] hash = md.digest(src); 65 66 return hash.toHexString!(LetterCase.upper); 67 } 68 69 string Hash(int bits)(scope const(void[])[] src...) 70 if (bits == 128 || bits == 160) 71 { 72 static if (bits == 128) 73 return MD5(src); 74 else 75 return RIPEMD160(src); 76 } 77 78 ubyte[] strToByte_hex(string input) 79 { 80 if (input == string.init) 81 { 82 return null; 83 } 84 85 Appender!(ubyte[]) app; 86 87 for (size_t i; i < input.length; i += 2) 88 { 89 app.put(input[i .. i + 2].to!ubyte(16)); 90 } 91 92 return app.data; 93 } 94 95 string byteToStr_hex(T = ubyte)(T[] buffer) 96 { 97 if (buffer.length == 0) 98 { 99 return string.init; 100 } 101 102 Appender!string app; 103 104 foreach (b; buffer) 105 { 106 app.put(rightJustify(b.to!string(16).toUpper(), 2, '0')); 107 } 108 109 return app.data; 110 } 111 112 bool isIPAddress(string ip) 113 { 114 auto re = regex(`^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$`); 115 return !match(ip, re).empty(); 116 } 117 118 long ipToLong(string ip) 119 { 120 auto part = split(ip, "."); 121 122 if (part.length != 4) 123 { 124 return 0; 125 } 126 127 long r = as!long(part[3], 0); 128 129 for (int i = 2; i >= 0; i--) 130 { 131 r += as!long(part[i], 0) << 8 * (3 - i); 132 } 133 134 return r; 135 } 136 137 string ipFromLong(long ipInt) 138 { 139 string[4] part; 140 141 for (int i = 3; i >= 0; i--) 142 { 143 part[i] = to!string(ipInt % 256); 144 ipInt /= 256; 145 } 146 147 return mergeString( 148 part[0].to!string, ".", 149 part[1].to!string, ".", 150 part[2].to!string, ".", 151 part[3].to!string 152 ); 153 } 154 155 string mergeString(Params...)(Params params) 156 { 157 Appender!string ret; 158 159 foreach(str; params) 160 { 161 ret.put(str); 162 } 163 164 return ret.data; 165 } 166 167 T as(T = int)(string src, T defaultValue = T.init) 168 { 169 try 170 { 171 return to!T(src); 172 } 173 catch (Exception e) 174 { 175 return defaultValue; 176 } 177 } 178 179 string floatAsString(T = double)(T value) if (is(Unqual!T == double) || is(Unqual!T == float) || is(Unqual!T == real)) 180 { 181 long l = cast(long)value; 182 T f = value - l; 183 184 return to!string(l) ~ ((f > 0) ? f.to!string[1 .. $] : ""); 185 } 186 187 string dateTimeToString(DateTime dt) // 2017-12-01 00:01:01 188 { 189 return dt.date().toISOExtString() ~ " " ~ dt.timeOfDay().toISOExtString(); 190 } 191 192 DateTime dateTimeFromString(string dt, DateTime defaultValue = DateTime.init) 193 { 194 if ((dt.length > 10) && (dt[10] == ' ')) 195 { 196 dt = dt.replace(" ", "T"); 197 } 198 199 try 200 { 201 return DateTime.fromISOExtString(dt); 202 } 203 catch (Exception e) 204 { 205 return defaultValue; 206 } 207 } 208 209 SysTime sysTimeFromString(string dt, SysTime defaultValue = SysTime.init) 210 { 211 dt = strip(dt); 212 213 if ((dt.length > 10) && (dt[10] == 32)) 214 { 215 dt = dt.replace("\x20", "T"); 216 } 217 218 try 219 { 220 return SysTime.fromISOExtString(dt); 221 } 222 catch (Exception e) 223 { 224 return defaultValue; 225 } 226 } 227 228 DateTime now() 229 { 230 return cast(DateTime)Clock.currTime; 231 } 232 233 private const long TICK_BASE = 1460004240; 234 235 long currTimeTick() 236 { 237 return Clock.currTime().toUnixTime() - TICK_BASE; 238 } 239 240 SysTime currTimeFromTick(long tick) 241 { 242 return SysTime.fromUnixTime(tick + TICK_BASE); 243 } 244 245 bool inArray(T)(in T[] _array, in T v) 246 { 247 return _array.any!(x => x == v); 248 } 249 250 bool inArray(T)(in T[] _array, in T[] _sub_array) 251 { 252 foreach (v; _sub_array) 253 { 254 if (!inArray!T(_array, v)) 255 { 256 return false; 257 } 258 } 259 260 return true; 261 } 262 263 bool inArray(T)(in T[][] _array, in T[] _sub_array) 264 { 265 foreach (v; _array) 266 { 267 if (v == _sub_array) 268 { 269 return true; 270 } 271 } 272 273 return false; 274 } 275 276 bool hasCross(T)(in T[] _array, in T[] arr) 277 { 278 foreach (v; arr) 279 { 280 if (inArray!T(_array, v)) 281 { 282 return true; 283 } 284 } 285 286 return false; 287 } 288 289 long pos(T)(in T[] _array, T _value) 290 { 291 foreach (k, v; _array) 292 { 293 if (v == _value) 294 { 295 return cast(long)k; 296 } 297 } 298 299 return -1; 300 } 301 302 T[][] combinationsRecursive(T)(in T[] data, size_t partLength) 303 { 304 if (partLength > data.length) 305 { 306 return null; 307 } 308 309 T[][] result; 310 311 if (partLength == 1) 312 { 313 data.each!(a => result ~= [ a ]); 314 315 return result; 316 } 317 318 T[] _data = data.dup; 319 320 void recursive(ref T[][] result, in T[] t, size_t n, size_t m, T[] b, size_t M) 321 { 322 for (size_t i = n; i >= m; i--) 323 { 324 b[m - 1] = cast(T)(i - 1); 325 326 if (m > 1) 327 { 328 recursive(result, t, cast(T)(i - 1), cast(T)(m - 1), b, M); 329 } 330 else 331 { 332 T[] temp = new T[M]; 333 334 for (size_t j = 0; j < b.length; j++) 335 { 336 temp[j] = t[b[j]]; 337 } 338 339 result = temp ~ result; 340 } 341 } 342 } 343 344 T[] temp = new T[partLength]; 345 recursive(result, _data, _data.length, partLength, temp, partLength); 346 347 return result; 348 } 349 350 T_Value[T_Key] dupAssociativeArray(T_Value, T_Key)(T_Value[T_Key] srcArray) 351 { 352 T_Value[T_Key] ret = srcArray.dup; 353 354 foreach (k, ref v; ret) 355 { 356 v = srcArray[k].dup; 357 } 358 359 return ret; 360 } 361 362 T[][] dupArrayArray(T)(T[][] srcArray) 363 { 364 T[][] ret = srcArray.dup; 365 366 foreach (k, ref v; ret) 367 { 368 v = srcArray[k].dup; 369 } 370 371 return ret; 372 } 373 374 T[] dupClassArray(T)(T[] classArray) 375 { 376 T[] ret = classArray.dup; 377 378 foreach (k, ref v; ret) 379 { 380 v = new T(classArray[k]); 381 } 382 383 return ret; 384 } 385 386 string compressString(const string input) 387 { 388 return compressString(cast(ubyte[]) input); 389 } 390 391 string compressString(const scope void[] input) 392 { 393 return cast(string) compress(input); 394 } 395 396 string uncompressString(const string input) 397 { 398 return cast(string) uncompressUbytes(input); 399 } 400 401 ubyte[] uncompressUbytes(const string input) 402 { 403 if (input == string.init) 404 { 405 return null; 406 } 407 408 try 409 { 410 return cast(ubyte[]) uncompress(cast(ubyte[]) input); 411 } 412 catch (Exception) 413 { 414 return null; 415 } 416 } 417 418 419 __gshared InsecureRandomGenerator rnd; 420 421 struct InsecureRandomGenerator 422 { 423 private static Mt19937 generator; 424 425 static this() 426 { 427 generator.seed(unpredictableSeed); 428 } 429 430 T next(T = uint)(T min = T.min, T max = T.max) if (is(Unqual!T == uint) || is(Unqual!T == int) || is(Unqual!T == ubyte) || is(Unqual!T == byte) || is(Unqual!T == ulong) || is(Unqual!T == long) || is(Unqual!T == ushort) || is(Unqual!T == short) || is(Unqual!T == size_t)) 431 { 432 return uniform!("[]", T, T, typeof(generator))(min, max, generator); 433 } 434 }