1 /// Utilities not related to IRC.
2 module irc.util;
3 
4 import core.exception : OutOfMemoryError;
5 import core.stdc.stdlib : malloc, free;
6 
7 import std.algorithm;
8 import std.array;
9 import std.conv : emplace;
10 import std.exception;
11 import std.range;
12 import std.traits;
13 
14 auto values(Elems...)(auto ref Elems elems) if(is(CommonType!Elems))
15 {
16 	alias CommonType!Elems ElemType;
17 
18 	static struct StaticArray
19 	{
20 		ElemType[Elems.length] data = void;
21 		size_t i = 0;
22 
23 		bool empty() const
24 		{
25 			return i == data.length;
26 		}
27 
28 		ElemType front() const pure
29 		{
30 			return data[i];
31 		}
32 
33 		void popFront() pure
34 		{
35 			++i;
36 		}
37 
38 		enum length = data.length;
39 	}
40 
41 	StaticArray arr;
42 
43 	foreach(i, ref elem; elems)
44 		arr.data[i] = elem;
45 
46 	return arr;
47 }
48 
49 unittest
50 {
51 	assert(
52 	    values("one", "two", "three")
53 	    .joiner(" ")
54 	    .array() == "one two three");
55 }
56 
57 auto castRange(T, R)(R range)
58 {
59 	static struct Casted
60 	{
61 		R r;
62 
63 		T front()
64 		{
65 			return cast(T)r.front;
66 		}
67 
68 		alias r this;
69 	}
70 
71 	return Casted(range);
72 }
73 
74 T* alloc(T)()
75 {
76 	import core.exception : onOutOfMemoryError;
77 
78 	if(auto p = malloc(T.sizeof))
79 	{
80 		auto block = p[0 .. T.sizeof];
81 		return emplace!T(block);
82 	}
83 	else
84 	{
85 		onOutOfMemoryError();
86 		assert(false);
87 	}
88 }
89 
90 void dealloc(void* p)
91 {
92 	free(p);
93 }
94 
95 mixin template ExceptionConstructor()
96 {
97 	@safe pure nothrow
98 	this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
99 	{
100 		super(msg, file, line, next);
101 	}
102 }
103 
104 mixin template ExceptionConstructor(string defaultMessage)
105 {
106 	@safe pure nothrow
107 	this(string msg = defaultMessage, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
108 	{
109 		super(msg, file, line, next);
110 	}
111 }