1 // Copyright © 2017-2021 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     private 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  +  Check for equality between two interfaces
48  +/
49 bool wlIfaceEquals(immutable(WlInterface) a, immutable(WlInterface) b)
50 {
51     import core.stdc..string : strcmp;
52 
53     return a is b || strcmp(a._native.name, b._native.name) == 0;
54 }
55 
56 /++
57  +  Wraps a function literal into a try-catch statement.
58  +
59  +  Use this in functions called by C as exception cannot propagate there.
60  +  The try-catch statement will print a warning if an exception is thrown.
61  +  The try-catch statement will terminate runtime and exit program if an error is thrown.
62  +/
63 auto nothrowFnWrapper(alias fn)() nothrow
64 {
65     try
66     {
67         return fn();
68     }
69     catch(Exception ex)
70     {
71         import std.exception : collectException;
72         import std.stdio : stderr;
73         collectException(stderr.writeln("wayland-d: error in listener stub: "~ex.msg));
74     }
75     catch(Throwable err)
76     {
77         import core.runtime : Runtime;
78         import core.stdc.stdlib : exit;
79         import std.exception : collectException;
80         import std.stdio : stderr;
81         collectException(stderr.writeln("wayland-d: aborting due to error in listener stub: "~err.msg));
82         collectException(Runtime.terminate());
83         exit(1);
84     }
85     alias rt = typeof(fn());
86     static if (!is(rt == void))
87     {
88         return rt.init;
89     }
90 }
91 
92 
93 
94 /// static cache of objects that are looked-up by the address of their native
95 /// counter part
96 struct ObjectCache
97 {
98     private __gshared Object[void*] _cache;
99 
100     static void set (void* native, Object obj)
101     {
102         _cache[native] = obj;
103     }
104 
105     static Object get (void* native)
106     {
107         auto op = native in _cache;
108         return op ? *op : null;
109     }
110 
111     static void remove (void* native)
112     {
113         _cache.remove(native);
114     }
115 }
116 
117 /**
118  * Fixed-point number
119  *
120  * A `WlFixed` is a 24.8 signed fixed-point number with a sign bit, 23 bits
121  * of integer precision and 8 bits of decimal precision.
122  */
123 struct WlFixed
124 {
125     private uint _raw;
126     private union DI
127     {
128         long i;
129         double d;
130     }
131 
132     public this(uint raw)
133     {
134         _raw = raw;
135     }
136 
137     /**
138     * Converts an integer to a fixed-point number.
139     */
140     public static WlFixed create(in int val)
141     {
142         return WlFixed(val * 256);
143     }
144 
145     /**
146     * Converts a floating-point number to a fixed-point number.
147     */
148     public static WlFixed create(in double val)
149     {
150         DI u;
151         u.d = val + (3L << (51 - 8));
152         return WlFixed(cast(uint)(u.i));
153     }
154 
155     @property uint raw() const
156     {
157         return _raw;
158     }
159 
160     /**
161     * Converts a fixed-point number to an integer.
162     */
163     int opCast(T : int)() const
164     {
165         return _raw / 256;
166     }
167 
168     /**
169     * Converts a fixed-point number to a floating-point number.
170     */
171     double opCast(T : double)() const
172     {
173         DI u;
174         u.i = ((1023L + 44L) << 52) + (1L << 51) + f;
175         return u.d - (3L << 43);
176     }
177 }