added "iv.dynstring"
[iv.d.git] / meta.d
blobd5cc6e0e5067bbcccea2bf1d0032254c88a091c9
1 /* coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License ONLY.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // various "metaprogramming" utilities
17 // some of 'em duplicates functionality of `std.traits` and other such
18 // modules, to avoid importing the whole phobos. sorry.
19 module iv.meta is aliced;
22 // ////////////////////////////////////////////////////////////////////////// //
23 /** this is character buffer that can be used to build strings in CTFE.
25 * doing naive string concatenation in CTFE leads to excessive memory
26 * consuming and slowdowns ('cause compiler allocates a new string each
27 * time, and old one stays in memory forever). by using this simple
28 * buffer, we can cut CTFE code generation times and memory consumption
29 * by magnitutes (no, really!).
31 * it is better to create non-resizeable buffers. the easiest (albeit
32 * stupid ;-) way to do that is to increase initial buffer size until
33 * compilation succeeds. sorry, there is no `ctfeWrite()` in Aliced
34 * yet. i'm working on it.
36 public struct CTFECharBuffer(bool allowResize) {
37 // i see no reason to hide this
38 char[] buf;
39 uint bufpos = 0;
41 /// create buffer with the given size
42 this (uint maxsize) { buf.length = maxsize; }
44 static if (allowResize) {
45 /// put something into the buffer
46 void put (const(char)[] s...) nothrow @trusted {
47 if (s.length == 0) return;
48 if (buf.length-bufpos < s.length) {
49 //FIXME: overflows
50 uint newsz = cast(uint)(s.length-(buf.length-bufpos));
51 if (buf.length < 65536) newsz += cast(uint)buf.length*2; else newsz += 65536;
52 buf.length = newsz;
54 assert(buf.length-bufpos >= s.length);
55 buf[bufpos..bufpos+s.length] = s[];
56 bufpos += cast(uint)s.length;
58 } else {
59 /// put something into the buffer
60 void put (const(char)[] s...) nothrow @trusted @nogc {
61 if (s.length == 0) return;
62 if (buf.length-bufpos < s.length) assert(0, "out of buffer");
63 buf[bufpos..bufpos+s.length] = s[];
64 bufpos += cast(uint)s.length;
68 /// put lo-cased ASCII char into the buffer
69 void putLoCased() (char ch) nothrow @trusted {
70 if (ch >= 'A' && ch <= 'Z') ch += 32;
71 put(ch);
74 /// put string with lo-cased first char into the buffer
75 void putStrLoCasedFirst() (const(char)[] s...) nothrow @trusted {
76 if (s.length == 0) return;
77 putLoCased(s[0]);
78 put(s[1..$]);
81 /// put string into the buffer with all chars lo-cased
82 void putStrLoCased() (const(char)[] s...) nothrow @trusted {
83 if (s.length == 0) return;
84 foreach (char ch; s) {
85 if (ch >= 'A' && ch <= 'Z') ch += 32;
86 put(ch);
90 /// get buffer as string.
91 /// WARNING! don't modify buffer after this! i won't put any guards here.
92 @property string asString () const nothrow @trusted @nogc => cast(string)buf[0..bufpos];
96 // ////////////////////////////////////////////////////////////////////////// //
97 /// removes all qualifiers, if any, from type `T`
98 template Unqual(T) {
99 static if (is(T U == immutable U)) alias Unqual = U;
100 else static if (is(T U == shared inout const U)) alias Unqual = U;
101 else static if (is(T U == shared inout U)) alias Unqual = U;
102 else static if (is(T U == shared const U)) alias Unqual = U;
103 else static if (is(T U == shared U)) alias Unqual = U;
104 else static if (is(T U == inout const U)) alias Unqual = U;
105 else static if (is(T U == inout U)) alias Unqual = U;
106 else static if (is(T U == const U)) alias Unqual = U;
107 else alias Unqual = T;
111 // ////////////////////////////////////////////////////////////////////////// //
112 /// is `T` char, wchar, or dchar? can ignore qualifiers if `unqual` is `true`.
113 template isAnyCharType(T, bool unqual=false) {
114 static if (unqual) private alias UT = Unqual!T; else private alias UT = T;
115 enum isAnyCharType = is(UT == char) || is(UT == wchar) || is(UT == dchar);
119 // ////////////////////////////////////////////////////////////////////////// //
120 /// is `T` wchar, or dchar? can ignore qualifiers if `unqual` is `true`.
121 template isWideCharType(T, bool unqual=false) {
122 static if (unqual) private alias UT = Unqual!T; else private alias UT = T;
123 enum isWideCharType = is(UT == wchar) || is(UT == dchar);