1 module dud.resolve.confs; 2 3 import std.algorithm.iteration : each, filter, map; 4 import std.algorithm.searching : all, any, canFind; 5 import std.array : array, empty, front; 6 import std.format : format; 7 import std.typecons : Flag; 8 import std.range : chain; 9 import std.stdio; 10 11 import dud.resolve.positive; 12 import dud.resolve.conf; 13 import dud.semver.versionrange; 14 15 @safe pure: 16 17 private immutable nothing = Conf("", IsPositive.no); 18 19 struct Confs { 20 import std.algorithm.iteration : map; 21 22 @safe pure: 23 Conf[] confs; 24 25 this(const(Conf)[] input) { 26 import std.algorithm.iteration : each; 27 this.insert(input); 28 } 29 30 Confs dup() const { 31 import std.array : array; 32 return Confs(this.confs.map!(it => it.dup).array); 33 } 34 35 void insert(const(Conf[]) cs) { 36 cs.each!(it => this.insert(it)); 37 } 38 39 void insert(const(Conf) c) { 40 import std.algorithm.sorting : sort; 41 42 // Negativ all means nothing can be added anymore 43 if(!this.confs.empty && this.confs.front == nothing) { 44 return; 45 } 46 47 // Got a new nothing 48 if(c == nothing) { 49 this.confs = [ nothing.dup() ]; 50 return; 51 } 52 53 // Already in ignore 54 if(canFind(this.confs, c)) { 55 return; 56 } 57 58 this.confs ~= Conf(c.conf, c.isPositive); 59 this.confs = normalize(this.confs); 60 } 61 62 Confs invert() const { 63 return this.confs.map!(it => it.invert()).array.Confs; 64 } 65 66 bool opEquals(const(Confs) other) const { 67 return this.confs.length == other.confs.length 68 && this.confs.all!(c => canFind(other.confs, c)); 69 } 70 } 71 72 private Conf[] normalize(Conf[] toNorm) { 73 Conf[] ret; 74 outer: foreach(idx, it; toNorm) { 75 Conf inv = it.invert(); 76 foreach(jdx, jt; toNorm) { 77 if(idx != jdx && inv == jt) { 78 continue outer; 79 } 80 } 81 ret ~= it; 82 } 83 const everything = Conf("", IsPositive.yes); 84 if(canFind(ret, everything)) { 85 ret = ret.filter!(it => it == everything 86 || it.isPositive == IsPositive.no) 87 .array; 88 } 89 return ret; 90 } 91 92 /* 93 private bool isOkayToInsert(const(Conf[]) arr, const(Conf) it) { 94 const isNeg = it.isPositive == IsPositive.no; 95 const negPr = !isNegativPresent(arr, it); 96 const cf = !canFind(arr, it); 97 98 return (isNeg || negPr) && cf; 99 } 100 101 private bool isNegativPresent(const(Conf[]) arr, const(Conf) it) { 102 return arr 103 .filter!(a => a.isPositive == IsPositive.no) 104 .any!(a => a.conf == it.conf); 105 } 106 107 private Conf[] normalize(Conf[] arr) { 108 return arr 109 .filter!( 110 it => !isNegativPresent(arr, it) || it.isPositive == IsPositive.no) 111 .array; 112 }*/ 113 114 bool allowsAll(const(Confs) a, const(Confs) b) { 115 return b.confs.all!(it => allowsAny(a, it)); 116 } 117 118 bool allowsAny(const(Confs) a, const(Confs) b) { 119 return b.confs.empty || b.confs.any!(it => allowsAny(a, it)); 120 } 121 122 bool allowsAll(const(Confs) a, const(Conf) b) { 123 static import dud.resolve.conf; 124 return !a.confs.empty 125 && a.confs.any!(it => dud.resolve.conf.allowsAll(it, b)); 126 } 127 128 bool allowsAny(const(Confs) a, const(Conf) b) { 129 static import dud.resolve.conf; 130 const t = !a.confs.empty 131 && a.confs.any!(it => dud.resolve.conf.allowsAny(it, b)); 132 return t; 133 } 134 135 // TODO this one is having some problems 136 Confs intersectionOf(const(Confs) a, const(Confs) b) { 137 import std.algorithm.setops : cartesianProduct; 138 import std.algorithm.iteration : joiner; 139 140 Confs ret; 141 foreach(aIt; a.confs) { 142 foreach(bIt; b.confs) { 143 Confs i = dud.resolve.conf.intersectionOf(aIt, bIt); 144 foreach(abIt; i.confs) { 145 ret.insert(abIt); 146 } 147 } 148 } 149 return ret; 150 } 151 152 Confs differenceOf(const(Confs) a, const(Confs) b) { 153 Conf[] neg = b.confs 154 .map!(it => it.isPositive == IsPositive.no 155 ? it.dup 156 : Conf(it.conf, IsPositive.no)) 157 .array; 158 159 Conf[] ret = a.confs.map!(it => it.dup).array ~ neg; 160 return Confs(ret); 161 } 162 163 /** Return if a is a subset of b, or if a and b are disjoint, or 164 if a and b overlap 165 */ 166 SetRelation relation(const(Confs) a, const(Confs) b) pure { 167 if(b.allowsAll(a)) { 168 return SetRelation.subset; 169 } 170 if(b.allowsAny(a)) { 171 return SetRelation.overlapping; 172 } 173 return SetRelation.disjoint; 174 }