1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 module thrift.internal.ctfe; 21 22 import std.conv : to; 23 import std.traits; 24 25 /* 26 * Simple eager join() for strings, std.algorithm.join isn't CTFEable yet. 27 */ 28 string ctfeJoin(string[] strings, string separator = ", ") { 29 string result; 30 if (strings.length > 0) { 31 result ~= strings[0]; foreach(s;strings[1..$])32 foreach (s; strings[1..$]) { 33 result ~= separator ~ s; 34 } 35 } 36 return result; 37 } 38 39 /* 40 * A very primitive to!string() implementation for floating point numbers that 41 * is evaluatable at compile time. 42 * 43 * There is a wealth of problems associated with the algorithm used (e.g. 5.0 44 * prints as 4.999…, incorrect rounding, etc.), but a better alternative should 45 * be included with the D standard library instead of implementing it here. 46 */ 47 string ctfeToString(T)(T val) if (isFloatingPoint!T) { 48 if (val is T.nan) return "nan"; 49 if (val is T.infinity) return "inf"; 50 if (val is -T.infinity) return "-inf"; 51 if (val is 0.0) return "0"; 52 if (val is -0.0) return "-0"; 53 54 auto b = val; 55 56 string result; 57 if (b < 0) { 58 result ~= '-'; 59 b *= -1; 60 } 61 62 short magnitude; 63 while (b >= 10) { 64 ++magnitude; 65 b /= 10; 66 } 67 while (b < 1) { 68 --magnitude; 69 b *= 10; 70 } 71 72 foreach (i; 0 .. T.dig) { 73 if (i == 1) result ~= '.'; 74 75 auto first = cast(ubyte)b; 76 result ~= to!string(first); 77 78 b -= first; 79 import std.math; 80 if (b < pow(10.0, i - T.dig)) break; 81 b *= 10; 82 } 83 84 if (magnitude != 0) result ~= "e" ~ to!string(magnitude); 85 return result; 86 } 87 88 unittest { 89 import std.algorithm; 90 static assert(ctfeToString(double.infinity) == "inf"); 91 static assert(ctfeToString(-double.infinity) == "-inf"); 92 static assert(ctfeToString(double.nan) == "nan"); 93 static assert(ctfeToString(0.0) == "0"); 94 static assert(ctfeToString(-0.0) == "-0"); 95 static assert(ctfeToString(2.5) == "2.5"); 96 static assert(ctfeToString(3.1415).startsWith("3.141")); 97 static assert(ctfeToString(2e-200) == "2e-200"); 98 } 99