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