1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity high) 4 module common; 5 6 import tango.io.stream.Format; 7 public import tango.io.Stdout; 8 public import tango.text.convert.Layout : Layout; 9 public import core.vararg; 10 11 /// General int. 12 alias int_t = sizediff_t; 13 /// General uint. 14 alias uint_t = size_t; 15 16 /// Signed size type. 17 alias ssize_t = sizediff_t; 18 19 /// Const character aliases. 20 alias cchar = const(char); 21 alias cwchar = const(wchar); /// ditto 22 alias cdchar = const(dchar); /// ditto 23 /// Constant string aliases. 24 alias cstring = const(char)[]; 25 alias cwstring = const(wchar)[]; /// ditto 26 alias cdstring = const(dchar)[]; /// ditto 27 28 /// Binary, typeless string. 29 alias binstr = ubyte[]; 30 alias cbinstr = const(ubyte)[]; /// ditto 31 32 alias FormatOut = FormatOutput!(char); 33 /// Global formatter instance. 34 static Layout!(char) Format; 35 static typeof(&Stdout.format) Printf; 36 static typeof(&Stdout.formatln) Printfln; 37 static this() 38 { 39 Format = new typeof(Format); 40 Printf = &Stdout.format; 41 Printfln = &Stdout.formatln; 42 } 43 44 /// Full range negative integer. 45 struct Neg 46 { 47 uint_t n; 48 alias n this; 49 } 50 51 /// Writes a message to stdout. 52 scope class UnittestMsg 53 { 54 cstring msg; 55 cstring passed = "Passed!\n"; 56 this(cstring msg) 57 { 58 this.msg = msg; 59 Stdout(msg); 60 } 61 ~this() 62 { 63 auto tabs = "\t\t\t\t\t\t\t\t\t\t"; 64 auto num = 10 - msg.length/8 - 1; 65 Stdout(tabs[0..num] ~ passed); 66 } 67 } 68 69 // Check version IDs. 70 version(D1) { 71 version(D2) 72 static assert(0, "Can't have both D1 and D2 defined."); 73 } 74 else 75 version(D2) 76 {} 77 else 78 static assert(0, "Either -version=D1 or D2 must be defined."); 79 80 /// Constructs a compile-time tuple. 81 template Tuple(T...) 82 { 83 alias Tuple = T; 84 } 85 86 /// Converts an array to a tuple. 87 template Array2Tuple(alias T) 88 { 89 static if (T.length == 0) 90 alias Array2Tuple = Tuple!(); 91 else static if (T.length == 1) 92 alias Array2Tuple = Tuple!(T[0]); 93 else 94 alias Array2Tuple = Tuple!(T[0], Array2Tuple!(T[1..$])); 95 } 96 97 /// Supports expressions like: 13 in Set(8,13,0) 98 auto Set(Xs...)(Xs xs) 99 { 100 struct Set 101 { 102 Xs xs; 103 bool opBinaryRight(string op : "in", X)(X x) 104 { 105 static if (is(X == class) || is(X dummy : P*, P)) // Class or pointer? 106 { 107 foreach (x_; xs) 108 if (x is x_) 109 return true; 110 } 111 else 112 foreach (x_; xs) 113 if (x == x_) 114 return true; 115 return false; 116 } 117 } 118 return Set(xs); 119 } 120 121 /// Like Set, but used like: 13.In(8,13,0) 122 /// NB: DMD generates worse code for Set() because of the inner struct. 123 bool In(X, Xs...)(X x, Xs xs) 124 { 125 static if (is(X == class) || is(X dummy : P*, P)) // Class or pointer? 126 { 127 foreach (x_; xs) 128 if (x is x_) 129 return true; 130 } 131 else 132 foreach (x_; xs) 133 if (x == x_) 134 return true; 135 return false; 136 } 137 138 void testSet() 139 { 140 scope msg = new UnittestMsg("Testing functions Set() and In()."); 141 auto x = new Object(); 142 assert(x.In(x)); 143 assert(x in Set(x)); 144 assert((&x).In(&x)); 145 assert(&x in Set(&x)); 146 assert(null.In(null)); 147 assert(null in Set(null)); 148 assert(1.In(1,2,3)); 149 assert(1 in Set(1,2,3)); 150 assert("unittest".In("xyz", "", cast(cstring)null, "unittest")); 151 assert("unittest" in Set("xyz", "", cast(cstring)null, "unittest")); 152 assert(!'x'.In('y', 'z')); 153 assert('x' !in Set('y', 'z')); 154 }