1 // SemiTwist D Tools: Library 2 // Written in the D programming language. 3 4 module semitwist.util.ver; 5 6 import std.compiler; 7 import std.conv; 8 import std.math; 9 import std.stdio; 10 import std..string; 11 12 import semitwist.util.all; 13 14 //TODO: Support versions that have different semantics 15 //TODO: Document ordering semantics of this 16 //TODO: This should all work at compile-time 17 struct Ver 18 { 19 uint[] ver; 20 21 //TODO: Get rid of this "static if" (but not the func) after dropping support for DMD 2.058 22 static if(vendor != Vendor.digitalMars || version_minor >= 59) 23 const int opCmp(const(Ver) v) 24 { 25 return opCmp(v); 26 } 27 28 const int opCmp(ref const(Ver) v) 29 { 30 for(int i=0; i < reduce!"a<b?a:b"([this.ver.length, v.ver.length]); i++) 31 { 32 if(this.ver[i] != v.ver[i]) 33 return this.ver[i] - v.ver[i]; 34 } 35 36 if(this.ver.length > v.ver.length) 37 return 1; 38 else if(this.ver.length < v.ver.length) 39 return -1; 40 41 return 0; 42 } 43 44 //TODO: Get rid of this "static if" (but not the func) after dropping support for DMD 2.058 45 static if(vendor != Vendor.digitalMars || version_minor >= 59) 46 const bool opEquals(const(Ver) v) 47 { 48 return opEquals(v); 49 } 50 51 const bool opEquals(ref const(Ver) v) 52 { 53 return this.opCmp(v) == 0; 54 } 55 56 static if(useNoThrowSafeToHash) 57 { 58 const nothrow @trusted hash_t toHash() 59 { 60 string str; 61 try 62 str = toString(); 63 catch(Exception e) 64 {} // Yes, that's right, I actually have to pull a Java 65 // and squelch exceptions for the time being. *$^@&!# 66 return typeid(string).getHash(&str); 67 } 68 } 69 else 70 { 71 const hash_t toHash() 72 { 73 auto str = toString(); 74 return typeid(string).getHash(&str); 75 } 76 } 77 78 const string toString() 79 { 80 return join(to!(string[])(ver), "."); 81 } 82 } 83 84 Ver toVer(string str) 85 { 86 auto strParts = str.ctfe_split("."); 87 uint[] verParts; 88 verParts.length = strParts.length; 89 90 foreach(i, strPart; strParts) 91 verParts[i] = ctfe_to!uint(strPart); 92 93 return Ver(verParts); 94 } 95 96 mixin(unittestSemiTwistDLib(q{ 97 mixin(deferAssert!(`Ver([5,5,5]) == Ver([5,5,5])`)); 98 mixin(deferAssert!(`Ver([5,5,0]) != Ver([5,5,5])`)); 99 mixin(deferAssert!(`Ver([5,5]) != Ver([5,5,5])`)); 100 mixin(deferAssert!(`Ver([2,10,3]) == Ver([2,10,3])`)); 101 102 mixin(deferAssert!(`Ver([5,5,5]) > Ver([5,5,1])`)); 103 mixin(deferAssert!(`Ver([5,5,5]) > Ver([5,1,5])`)); 104 mixin(deferAssert!(`Ver([5,5,5]) > Ver([1,5,5])`)); 105 106 mixin(deferAssert!(`Ver([5,5,0]) < Ver([5,5,5])`)); 107 108 mixin(deferAssert!(`Ver([5,5,0]) > Ver([5,5])`)); 109 mixin(deferAssert!(`Ver([5,5]) < Ver([5,5,0])`)); 110 111 mixin(deferAssert!(`Ver([1,10]) > Ver([1,1])`)); 112 113 mixin(deferEnsure!(`"2.10.3".toVer().ver`, `_ == [cast(uint)2,10,3]`)); 114 mixin(deferEnsure!(`"2.10.3".toVer()`, `_ == Ver([2,10,3])`)); 115 mixin(deferEnsure!(`Ver([2,10,3]).toString()`, `_ == "2.10.3"`)); 116 }));