1 module uim.oop.mixins.properties.expandable; 2 3 import std..string; 4 import uim.core; 5 6 // Mixin for expandable string datatypes 7 template XString(string name) { 8 const char[] XString = " 9 string _"~name~"; 10 @safe auto "~name~"() { return _"~name~"; } 11 12 @safe O "~name~"(this O)(string[] addValues...) { this."~name~"(addValues); return cast(O)this; } 13 @safe O "~name~"(this O)(string[] addValues) { _"~name~" ~= addValues.join(); return cast(O)this; } 14 15 @safe O clear"~name.capitalize~"(this O)() { _"~name~" = null; return cast(O)this; } 16 "; 17 } 18 unittest { 19 class Test { mixin(XString!"a"); } 20 assert((new Test).a("x").a == "x"); 21 assert((new Test).a("x").a("x").a == "xx"); 22 assert((new Test).a("x", "x").a == "xx"); 23 assert((new Test).a(["x", "x"]).a == "xx"); 24 assert((new Test).a("x").clearA.a == ""); 25 } 26 27 // Mixin for expandable string array datatypes 28 template XStringArray(string name) { 29 const char[] Name = name.capitalize; 30 const char[] XStringArray = " 31 string[] _"~name~"; 32 @safe auto "~name~"() { return _"~name~"; } 33 34 @safe O "~name~"(this O)(string[] values...) { this."~name~"(values); return cast(O)this; } 35 @safe O "~name~"(this O)(string[] values) { _"~name~" ~= values; return cast(O)this; } 36 37 @safe O remove"~Name~"(this O)(string[] values...) { this.remove"~Name~"(values); return cast(O)this; } 38 @safe O remove"~Name~"(this O)(string[] values) { 39 foreach(value; values) _"~name~" = _"~name~".sub(value); return cast(O)this; } 40 41 @safe O clear"~Name~"(this O)() { _"~name~" = null; return cast(O)this; } 42 "; 43 } 44 unittest { 45 class Test { mixin(XStringArray!"a"); } 46 assert((new Test).a("x").a == ["x"]); 47 assert((new Test).a("x").a("x").a == ["x", "x"]); 48 assert((new Test).a("x", "x").a == ["x", "x"]); 49 assert((new Test).a("x").clearA.a == null); 50 assert((new Test).a(["a", "b", "c"]).a == ["a", "b", "c"]); 51 assert((new Test).a(["a", "b", "c"]).removeA("x").a == ["a", "b", "c"]); 52 assert((new Test).a(["a", "b", "c", "a"]).a == ["a", "b", "c", "a"]); 53 assert((new Test).a(["a", "b", "c", "a"]).removeA("a").a == ["b", "c", "a"]); 54 assert((new Test).a(["a", "b", "c", "a"]).removeA(["a"]).a == ["b", "c", "a"]); 55 //assert((new Test).a(["a", "b", "c"]).removeA(["a"], true).a == ["b", "c"]); 56 } 57 58 // Mixin for expandable string associative array datatypes 59 template XStringAA(string name) { 60 const char[] Name = name.capitalize; 61 const char[] XStringAA = " 62 string[string] _"~name~"; 63 @safe auto "~name~"() { return _"~name~"; } 64 @safe auto "~name~"(string key) { return _"~name~".get(key, ``); } 65 66 @safe O "~name~"(this O)(string key, string value) { _"~name~"[key] = value; return cast(O)this; } 67 @safe O "~name~"(this O)(string[string] addValues) { foreach(kv; addValues.byKeyValue) _"~name~"[kv.key] = kv.value; return cast(O)this; } 68 69 @safe O remove"~Name~"(this O)(string[] values...) { this.remove(values); return cast(O)this; } 70 @safe O remove"~Name~"(this O)(string[] values) { foreach(value; values) _name = _"~name~".remove(value); return cast(O)this; } 71 72 @safe O clear"~Name~"(this O)() { _"~name~" = null; return cast(O)this; } 73 "; 74 } 75 unittest { 76 class Test { mixin(XStringAA!"a"); } 77 assert((new Test).a(["a":"x"]).a == ["a":"x"]); 78 assert((new Test).a("a", "x").a == ["a":"x"]); 79 assert((new Test).a("a", "x").clearA.a == null); 80 } 81 82 template XPropertyAA(string key, string value, string name) { 83 const char[] Name = capitalize(name); 84 const char[] datatype = value~`[`~key~`]`; 85 86 const char[] XPropertyAA = ` `~datatype~` _`~name~`; 87 @safe auto `~name~`() { return _`~name~`; } 88 @safe auto `~name~`(`~key~` key) { return _`~name~`[key]; } 89 90 @safe auto `~name~`(this O)(`~key~`[] keys...) { return this.`~name~`(keys); } 91 @safe auto `~name~`(this O)(`~key~`[] keys) { return _`~name~`.select(keys); } 92 93 @safe O `~name~`(this O)(`~datatype~` values) { _`~name~` = _`~name~`.add(values); return cast(O)this; } 94 95 @safe O `~name~`Init(this O)(`~key~`[] keys, `~value~` value) { foreach(k; keys) _`~name~`[k] = value; return cast(O)this; } 96 @safe O `~name~`Add(this O)(`~datatype~` values) { _`~name~` = _`~name~`.add(values); return cast(O)this; } 97 @safe O `~name~`Sub(this O)(`~datatype~` values) { _`~name~` = _`~name~`.sub(values); return cast(O)this; } 98 99 @safe O remove`~Name~`(this O)(`~key~`[] keys...) { return this.remove`~Name~`(keys); return cast(O)this; } 100 @safe O remove`~Name~`(this O)(`~key~`[] keys) { _`~name~` = _`~name~`.sub(keys); return cast(O)this; } 101 102 @safe O clear`~Name~`(this O)() { _`~name~` = _`~name~`.clear; return cast(O)this; } 103 `; 104 } 105 unittest { 106 class Test { mixin(XPropertyAA!("int", "double", "a")); } 107 assert((new Test).a([1:1.0]).a[1] == 1.0); 108 assert((new Test).a([1:1.0]).a.hasKey(1)); 109 assert((new Test).a([1:1.0]).a([2:3.0]).a.hasKey(2)); 110 assert(!(new Test).a([1:1.0, 2:3.0]).aSub([2:3.0]).a.hasKey(2)); 111 assert((new Test).aInit([1, 2], 1.0).a[1] == 1.0); 112 } 113 114 template XPropertyArray(string datatype, string name) { 115 const char[] Name = capitalize(name); 116 const char[] XPropertyArray = ` 117 `~datatype~`[] _`~name~`; 118 @safe auto `~name~`() { return _`~name~`; } 119 120 @safe O `~name~`(this O)(`~datatype~`[] values...) { _`~name~` = _`~name~`.add(values); return cast(O)this; } 121 @safe O `~name~`(this O)(`~datatype~`[] values, bool unique = false) { _`~name~` = _`~name~`.add(values, unique); return cast(O)this; } 122 123 @safe O remove`~Name~`(this O)(`~datatype~`[] values...) { remove`~Name~`(values); return cast(O)this; } 124 @safe O remove`~Name~`(this O)(`~datatype~`[] values) { 125 foreach(value; values) if (value.index(_`~name~`) != -1) _`~name~`.remove(value.index(_`~name~`)); 126 return cast(O)this; } 127 128 @safe O clear`~Name~`(this O)() { _`~name~` = null; return cast(O)this; } 129 `; 130 } 131 unittest { 132 class Test { mixin(XPropertyArray!("int", "a")); } 133 assert((new Test).a(0).a == [0]); 134 assert((new Test).a(0).a(1).a == [0, 1]); 135 assert((new Test).a(0, 1).a == [0, 1]); 136 assert((new Test).a(0).clearA.a == null); 137 assert((new Test).a([1, 2, 3]).a == [1, 2, 3]); 138 // assert((new Test).a([1, 2, 3]).removeA(4).a == [1, 2, 3]); 139 /* assert((new Test).a([1, 2, 3, 1]).a == [1, 2, 3, 1]); 140 assert((new Test).a([1, 2, 3, 1]).removeA(1).a == [2, 3, 1]); 141 assert((new Test).a([1, 2, 3, 1]).removeA([1]).a == [2, 3, 1]); */ 142 //assert((new Test).a(["a", "b", "c"]).removeA(["a"], true).a == ["b", "c"]); 143 }