1 /** 2 * Portable routines for functions that have different implementations on different platforms. 3 * 4 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved 5 * Authors: Walter Bright, https://www.digitalmars.com 6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/port.d, root/_port.d) 8 * Documentation: https://dlang.org/phobos/dmd_root_port.html 9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/port.d 10 */ 11 12 module dmd.root.port; 13 14 import core.stdc.ctype; 15 import core.stdc.errno; 16 import core.stdc.string; 17 import core.stdc.stdint; 18 import core.stdc.stdio; 19 import core.stdc.stdlib; 20 21 nothrow @nogc: 22 23 private extern (C) 24 { 25 version(CRuntime_DigitalMars) __gshared extern const(char)* __locale_decpoint; 26 27 version(CRuntime_Microsoft) 28 { 29 enum _OVERFLOW = 3; /* overflow range error */ 30 enum _UNDERFLOW = 4; /* underflow range error */ 31 32 int _atoflt(float* value, const(char)* str); 33 int _atodbl(double* value, const(char)* str); 34 } 35 } 36 37 extern (C++) struct Port 38 { 39 nothrow @nogc: 40 41 static int memicmp(scope const char* s1, scope const char* s2, size_t n) pure 42 { 43 int result = 0; 44 45 foreach (i; 0 .. n) 46 { 47 char c1 = s1[i]; 48 char c2 = s2[i]; 49 50 result = c1 - c2; 51 if (result) 52 { 53 result = toupper(c1) - toupper(c2); 54 if (result) 55 break; 56 } 57 } 58 return result; 59 } 60 61 static char* strupr(char* s) pure 62 { 63 char* t = s; 64 65 while (*s) 66 { 67 *s = cast(char)toupper(*s); 68 s++; 69 } 70 71 return t; 72 } 73 private extern (D) static bool resultOutOfRange(FloatingType)(const FloatingType x, const int errnoValue) 74 { 75 import core.stdc.math : HUGE_VAL, HUGE_VALF; 76 static if (is(FloatingType == double)) 77 const FloatingType hugeVal = HUGE_VAL; 78 else static if (is(FloatingType == float)) 79 const FloatingType hugeVal = HUGE_VALF; 80 else static assert(0, "This function does not support " ~ FloatingType); 81 82 if (errnoValue == ERANGE) 83 { 84 return x == hugeVal || x == 0.0f; 85 } 86 return false; 87 } 88 static bool isFloat32LiteralOutOfRange(scope const(char)* s) 89 { 90 errno = 0; 91 version (CRuntime_DigitalMars) 92 { 93 auto save = __locale_decpoint; 94 __locale_decpoint = "."; 95 scope(exit) 96 __locale_decpoint = save; 97 } 98 version (CRuntime_Microsoft) 99 { 100 float r; 101 int res = _atoflt(&r, s); 102 if (res == _UNDERFLOW || res == _OVERFLOW) 103 errno = ERANGE; 104 return errno == ERANGE; 105 } 106 else 107 { 108 const result = strtof(s, null); 109 return resultOutOfRange(result, errno); 110 } 111 } 112 113 static bool isFloat64LiteralOutOfRange(scope const(char)* s) 114 { 115 errno = 0; 116 version (CRuntime_DigitalMars) 117 { 118 auto save = __locale_decpoint; 119 __locale_decpoint = "."; 120 scope(exit) 121 __locale_decpoint = save; 122 } 123 version (CRuntime_Microsoft) 124 { 125 double r; 126 int res = _atodbl(&r, s); 127 if (res == _UNDERFLOW || res == _OVERFLOW) 128 errno = ERANGE; 129 return errno == ERANGE; 130 } 131 else 132 { 133 const result = strtod(s, null); 134 return resultOutOfRange(result, errno); 135 } 136 } 137 138 // Little endian 139 static void writelongLE(uint value, scope void* buffer) pure 140 { 141 auto p = cast(ubyte*)buffer; 142 p[3] = cast(ubyte)(value >> 24); 143 p[2] = cast(ubyte)(value >> 16); 144 p[1] = cast(ubyte)(value >> 8); 145 p[0] = cast(ubyte)(value); 146 } 147 148 // Little endian 149 static uint readlongLE(scope const void* buffer) pure 150 { 151 auto p = cast(const ubyte*)buffer; 152 return (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0]; 153 } 154 155 // Big endian 156 static void writelongBE(uint value, scope void* buffer) pure 157 { 158 auto p = cast(ubyte*)buffer; 159 p[0] = cast(ubyte)(value >> 24); 160 p[1] = cast(ubyte)(value >> 16); 161 p[2] = cast(ubyte)(value >> 8); 162 p[3] = cast(ubyte)(value); 163 } 164 165 // Big endian 166 static uint readlongBE(scope const void* buffer) pure 167 { 168 auto p = cast(const ubyte*)buffer; 169 return (((((p[0] << 8) | p[1]) << 8) | p[2]) << 8) | p[3]; 170 } 171 172 // Little endian 173 static uint readwordLE(scope const void* buffer) pure 174 { 175 auto p = cast(const ubyte*)buffer; 176 return (p[1] << 8) | p[0]; 177 } 178 179 // Big endian 180 static uint readwordBE(scope const void* buffer) pure 181 { 182 auto p = cast(const ubyte*)buffer; 183 return (p[0] << 8) | p[1]; 184 } 185 186 static void valcpy(scope void *dst, uint64_t val, size_t size) pure 187 { 188 assert((cast(size_t)dst) % size == 0); 189 switch (size) 190 { 191 case 1: *cast(ubyte *)dst = cast(ubyte)val; break; 192 case 2: *cast(ushort *)dst = cast(ushort)val; break; 193 case 4: *cast(uint *)dst = cast(uint)val; break; 194 case 8: *cast(ulong *)dst = cast(ulong)val; break; 195 default: assert(0); 196 } 197 } 198 }