1 // Copyright © 2017 Rémi Thebault
2 module wayland.util;
3 
4 import wayland.native.util;
5 
6 /// Implemented by type that wrap a native wayland struct pointer.
7 interface Native(wl_native)
8 {
9     /// Access the wrapped struct.
10     @property inout(wl_native)* native() inout;
11 }
12 
13 /// Utility mixin that implements Native for a type.
14 mixin template nativeImpl(wl_native)
15 {
16     private wl_native* _native;
17 
18     public final override @property inout(wl_native)* native() inout
19     {
20         return _native;
21     }
22 }
23 
24 
25 immutable class WlInterface
26 {
27     immutable wl_interface* _native;
28 
29     immutable this(immutable wl_interface* native)
30     {
31         this._native = native;
32     }
33 
34     @property immutable(wl_interface)* native() immutable
35     {
36         return _native;
37     }
38 
39     @property string name() immutable
40     {
41         import std.string : fromStringz;
42         return fromStringz(_native.name);
43     }
44 }
45 
46 /+
47  +  Wraps a function literal into a try-catch statement.
48  +
49  +  Use this in functions called by C as exception cannot propagate there.
50  +  The try-catch statement will print a warning if an exception is thrown.
51  +  The try-catch statement will terminate runtime and exit program if an error is thrown.
52  +/
53 auto nothrowFnWrapper(alias fn)() nothrow
54 {
55     try
56     {
57         return fn();
58     }
59     catch(Exception ex)
60     {
61         import std.exception : collectException;
62         import std.stdio : stderr;
63         collectException(stderr.writeln("wayland-d: error in listener stub: "~ex.msg));
64     }
65     catch(Throwable err)
66     {
67         import core.runtime : Runtime;
68         import core.stdc.stdlib : exit;
69         import std.exception : collectException;
70         import std.stdio : stderr;
71         collectException(stderr.writeln("wayland-d: aborting due to error in listener stub: "~err.msg));
72         collectException(Runtime.terminate());
73         exit(1);
74     }
75     alias rt = typeof(fn());
76     static if (!is(rt == void))
77     {
78         return rt.init;
79     }
80 }
81 
82 
83 
84 /// static cache of objects that are looked-up by the address of their native
85 /// counter part
86 struct ObjectCache
87 {
88     private __gshared Object[void*] _cache;
89 
90     static void set (void* native, Object obj)
91     {
92         _cache[native] = obj;
93     }
94 
95     static Object get (void* native)
96     {
97         auto op = native in _cache;
98         return op ? *op : null;
99     }
100 
101     static void remove (void* native)
102     {
103         _cache.remove(native);
104     }
105 }
106 
107 /**
108  * Fixed-point number
109  *
110  * A `WlFixed` is a 24.8 signed fixed-point number with a sign bit, 23 bits
111  * of integer precision and 8 bits of decimal precision.
112  */
113 struct WlFixed
114 {
115     private uint _raw;
116     private union DI
117     {
118         long i;
119         double d;
120     }
121 
122     public this(uint raw)
123     {
124         _raw = raw;
125     }
126 
127     /**
128     * Converts an integer to a fixed-point number.
129     */
130     public static WlFixed create(in int val)
131     {
132         return WlFixed(val * 256);
133     }
134 
135     /**
136     * Converts a floating-point number to a fixed-point number.
137     */
138     public static WlFixed create(in double val)
139     {
140         DI u;
141         u.d = val + (3L << (51 - 8));
142         return WlFixed(cast(uint)(u.i));
143     }
144 
145     @property uint raw() const
146     {
147         return _raw;
148     }
149 
150     /**
151     * Converts a fixed-point number to an integer.
152     */
153     int opCast(T : int)() const
154     {
155         return _raw / 256;
156     }
157 
158     /**
159     * Converts a fixed-point number to a floating-point number.
160     */
161     double opCast(T : double)() const
162     {
163         DI u;
164         u.i = ((1023L + 44L) << 52) + (1L << 51) + f;
165         return u.d - (3L << 43);
166     }
167 }