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 }