1 module parsing.data_sizes; 2 3 import std.algorithm; 4 import std..string; 5 import std.conv; 6 import std.uni; 7 8 class DataSizeParsing 9 { 10 private ulong[string] unitsTableBin; 11 private ulong[string] unitsTableDec; 12 this() 13 { 14 // Init lookup tables for division and multiplication sizes 15 unitsTableBin = [ 16 "b": 1, 17 "kib": 1024, 18 "mib": 1_048_576, 19 "gib": 1_073_741_824, 20 "tib": 1_099_511_627_776, 21 "pib": 1_125_899_906_842_620, 22 ]; 23 24 unitsTableDec = [ 25 "b": 1, 26 "kb": 1000, 27 "mb": 1_000_000, 28 "gb": 1_000_000_000, 29 "tb": 1_000_000_000_000, 30 "pb": 1_000_000_000_000_000 31 ]; 32 } 33 34 /// Parse a string i.e 10MiB to a value in bytes, supported suffixes are B, KiB..PiB and KB..PB 35 /// Params: 36 /// input = string in the form ie `10MiB` 37 /// Returns: ulong with the size in bytes based on the suffix 38 ulong fromHumanToBytes(string input) 39 { 40 string rawNum; 41 string suffix; 42 43 foreach (i, c; input) 44 { 45 // if we have anything in the suffix yet ignore the rest of the string 46 if (c.isNumber && suffix.length == 0) 47 rawNum ~= c; 48 else 49 suffix ~= c; 50 } 51 suffix = suffix.toLower; 52 // Don't bother with lookup if the suffix is too large to exist in the table 53 if (suffix.length <= 3 && suffix in unitsTableBin) 54 return parse!ulong(rawNum) * unitsTableBin[suffix]; 55 else if(suffix.length <= 2 && suffix in unitsTableDec) 56 return parse!ulong(rawNum) * unitsTableDec[suffix]; 57 else 58 throw new Exception(format("Invalid suffix %s", suffix)); 59 } 60 61 unittest 62 { 63 DataSizeParsing dsp = new DataSizeParsing; 64 65 assert(dsp.fromHumanToBytes("100MiB") == 104_857_600); 66 } 67 }