1 module dud.semver.comparision; 2 3 import std.array : empty; 4 import std.typecons : nullable, Nullable; 5 6 import dud.semver.semver; 7 import dud.semver.exception; 8 9 @safe pure: 10 11 int compare(const(SemVer) a, const(SemVer) b) nothrow { 12 if(a.major != b.major) { 13 return a.major < b.major ? -1 : 1; 14 } 15 16 if(a.minor != b.minor) { 17 return a.minor < b.minor ? -1 : 1; 18 } 19 20 if(a.patch != b.patch) { 21 return a.patch < b.patch ? -1 : 1; 22 } 23 24 if(a.preRelease.empty != b.preRelease.empty) { 25 return a.preRelease.empty ? 1 : -1; 26 } 27 28 size_t idx; 29 while(idx < a.preRelease.length && idx < b.preRelease.length) { 30 string aStr = a.preRelease[idx]; 31 string bStr = b.preRelease[idx]; 32 Nullable!uint aNumN = isAllNum(aStr); 33 Nullable!uint bNumN = isAllNum(bStr); 34 if(!aNumN.isNull() && !bNumN.isNull()) { 35 uint aNum = aNumN.get(); 36 uint bNum = bNumN.get(); 37 38 if(aNum != bNum) { 39 return aNum < bNum ? -1 : 1; 40 } 41 } else if(aStr != bStr) { 42 return aStr < bStr ? -1 : 1; 43 } 44 ++idx; 45 } 46 47 if(idx == a.preRelease.length && idx == b.preRelease.length) { 48 return 0; 49 } 50 51 return idx < a.preRelease.length ? 1 : -1; 52 } 53 54 Nullable!uint isAllNum(string s) nothrow { 55 import std.utf : byUTF; 56 import dud.semver.helper : isDigit; 57 import std.algorithm.searching : all; 58 import std.conv : to, ConvException; 59 60 const bool allNum = s.byUTF!char().all!isDigit(); 61 62 if(allNum) { 63 try { 64 return nullable(to!uint(s)); 65 } catch(Exception e) { 66 assert(false, s); 67 } 68 } 69 return Nullable!(uint).init; 70 } 71 72 unittest { 73 import std.format : format; 74 auto i = isAllNum("hello world"); 75 assert(i.isNull()); 76 77 i = isAllNum("12354"); 78 assert(!i.isNull()); 79 assert(i.get() == 12354); 80 81 i = isAllNum("0002354"); 82 assert(!i.isNull()); 83 assert(i.get() == 2354); 84 }