1 /*******************************************************************************
2 
3     Utilities for common CTFE operations needed for code generation
4 
5     NB: because this module is often used as purely compile-time dependency it
6         used built-in asserts instead of `ocean.core.Test` to reduce amount of
7         cyclic imports. `ocean.meta` modules in general are not supposed to
8         import anything outside of `ocean.meta`.
9 
10     Copyright:
11         Copyright (c) 2017 dunnhumby Germany GmbH. All rights reserved.
12 
13     License:
14         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
15         Alternatively, this file may be distributed under the terms of the Tango
16         3-Clause BSD License (see LICENSE_BSD.txt for details).
17 
18 *******************************************************************************/
19 
20 module ocean.meta.codegen.CTFE;
21 
22 import ocean.meta.types.Qualifiers;
23 import ocean.text.Ascii : toUpper;
24 
25 /*******************************************************************************
26 
27     Converts integer to string
28 
29     Params:
30         i = integer to convert
31 
32 *******************************************************************************/
33 
34 istring toString ( T ) ( T i )
35 {
36     if (i == 0)
37         return "0";
38 
39     if (i < 0)
40         return "-" ~ toStringImpl(- cast(long) i);
41 
42     return toStringImpl(cast(ulong) i);
43 }
44 
45 unittest
46 {
47     static assert (toString(0L) == "0");
48     static assert (toString(42L) == "42");
49     static assert (toString(-42L) == "-42");
50     static assert (toString(31L) == "31");
51     static assert (toString(-31L) == "-31");
52     static assert (toString(14L) == "14");
53     static assert (toString(long.max) == "9223372036854775807");
54     static assert (toString(long.min) == "-9223372036854775808");
55     static assert (toString(int.min) == "-2147483648");
56     static assert (toString(int.max) == "2147483647");
57     static assert (toString(short.min) == "-32768");
58     static assert (toString(short.max) == "32767");
59 }
60 
61 unittest
62 {
63     assert (toString(14UL) == "14");
64     static assert (toString(14UL) == "14");
65     assert (toString(ulong.max) == "18446744073709551615");
66     static assert (toString(ulong.max) == "18446744073709551615");
67 }
68 
69 unittest
70 {
71     assert (toString(cast(short) 14) == "14");
72 }
73 
74 istring toStringImpl ( ulong i )
75 {
76     istring digit = "0123456789";
77 
78     if (i == 0)
79         return "0";
80 
81     istring res;
82 
83     while (i > 0)
84     {
85         res = digit[i % 10] ~ res;
86         i /= 10;
87     }
88 
89     return res;
90 }
91 
92 /*******************************************************************************
93 
94     Utility to strip the part before the '.' in a string.
95 
96     Params:
97         name = string to scan
98 
99 *******************************************************************************/
100 
101 public istring stripQualifiedPrefix ( istring name )
102 {
103     ptrdiff_t idx = name.length - 1;
104 
105     while (idx > 0 && name[idx] != '.')
106         --idx;
107 
108     if (idx == 0)
109         return name;
110     else
111         return name[idx + 1 .. $];
112 }
113 
114 unittest
115 {
116     assert (stripQualifiedPrefix("aa.bb") == "bb");
117     static assert (stripQualifiedPrefix("aa.bb") == "bb");
118     assert (stripQualifiedPrefix("aa.bb.cc") == "cc");
119     static assert (stripQualifiedPrefix("aa.bb.cc") == "cc");
120     assert (stripQualifiedPrefix("aabb") == "aabb");
121     static assert (stripQualifiedPrefix("aabb") == "aabb");
122 }
123 
124 
125 /******************************************************************************
126 
127     Converts a snake_case name to a PascalCase.
128 
129     This function is designed for use at compile time and is thus not careful
130     about avoiding allocations.
131 
132     Params:
133         value = the snake_case value
134 
135     Returns:
136         The value in camel case
137 
138 ******************************************************************************/
139 
140 string snakeToPascal ( string value )
141 {
142     string result;
143     bool shouldCapitalize = true;
144 
145     foreach ( ch; value )
146     {
147         if ( ch == '_' )
148         {
149             shouldCapitalize = true;
150             continue;
151         }
152 
153         if ( shouldCapitalize )
154         {
155             result ~= toUpper([ch]);
156             shouldCapitalize = false;
157         }
158         else
159         {
160             result ~= ch;
161         }
162     }
163 
164     return result;
165 }
166 
167 ///
168 unittest
169 {
170     assert (snakeToPascal("") == "");
171     assert (snakeToPascal("a") == "A");
172     assert (snakeToPascal("Aaaa") == "Aaaa");
173     assert (snakeToPascal("aaaa_bbbbb") == "AaaaBbbbb");
174 }