@@ -2945,58 +2945,6 @@ if (isIntegral!T || isSomeChar!T || isBoolean!T)
2945
2945
}
2946
2946
2947
2947
2948
- private union EndianSwapper (T)
2949
- if (canSwapEndianness! T)
2950
- {
2951
- T value;
2952
- ubyte [T.sizeof] array;
2953
-
2954
- static if (is (immutable FloatingPointTypeOf! (T) == immutable float ))
2955
- uint intValue;
2956
- else static if (is (immutable FloatingPointTypeOf! (T) == immutable double ))
2957
- ulong intValue;
2958
-
2959
- }
2960
-
2961
- // Can't use EndianSwapper union during CTFE.
2962
- private auto ctfeRead (T)(const ubyte [T.sizeof] array)
2963
- if (__traits(isIntegral, T))
2964
- {
2965
- Unqual! T result;
2966
- version (LittleEndian )
2967
- foreach_reverse (b; array)
2968
- result = cast () cast (T) ((result << 8 ) | b);
2969
- else
2970
- foreach (b; array)
2971
- result = cast () cast (T) ((result << 8 ) | b);
2972
- return cast (T) result;
2973
- }
2974
-
2975
- // Can't use EndianSwapper union during CTFE.
2976
- private auto ctfeBytes (T)(const T value)
2977
- if (__traits(isIntegral, T))
2978
- {
2979
- ubyte [T.sizeof] result;
2980
- Unqual! T tmp = value;
2981
- version (LittleEndian )
2982
- {
2983
- foreach (i; 0 .. T.sizeof)
2984
- {
2985
- result[i] = cast (ubyte ) tmp;
2986
- tmp = cast () cast (T) (tmp >>> 8 );
2987
- }
2988
- }
2989
- else
2990
- {
2991
- foreach_reverse (i; 0 .. T.sizeof)
2992
- {
2993
- result[i] = cast (ubyte ) tmp;
2994
- tmp = cast ()(T) (tmp >>> 8 );
2995
- }
2996
- }
2997
- return result;
2998
- }
2999
-
3000
2948
/+ +
3001
2949
Converts the given value from the native endianness to big endian and
3002
2950
returns it as a `ubyte[n]` where `n` is the size of the given type.
@@ -3010,13 +2958,21 @@ if (__traits(isIntegral, T))
3010
2958
and therefore could vary from machine to machine (which could make it
3011
2959
unusable if you tried to transfer it to another machine).
3012
2960
+/
3013
- auto nativeToBigEndian (T)(const T val) @safe pure nothrow @nogc
2961
+ auto nativeToBigEndian (T)(const T val) @trusted pure nothrow @nogc
3014
2962
if (canSwapEndianness! T)
3015
2963
{
3016
- version ( LittleEndian )
3017
- return nativeToEndianImpl ! true ( val);
2964
+ static if (isFloatOrDouble ! T )
2965
+ return nativeToBigEndian ( * cast ( const UnsignedOfSize ! (T.sizeof) * ) & val);
3018
2966
else
3019
- return nativeToEndianImpl! false (val);
2967
+ {
2968
+ enum len = T.sizeof;
2969
+ ubyte [len] retval;
2970
+
2971
+ static foreach (i; 0 .. len)
2972
+ retval[i] = cast (ubyte )(val >> (len - i - 1 ) * 8 );
2973
+
2974
+ return retval;
2975
+ }
3020
2976
}
3021
2977
3022
2978
// /
@@ -3043,26 +2999,6 @@ if (canSwapEndianness!T)
3043
2999
assert (cd == bigEndianToNative! double (swappedCD));
3044
3000
}
3045
3001
3046
- private auto nativeToEndianImpl (bool swap, T)(const T val) @safe pure nothrow @nogc
3047
- if (__traits(isIntegral, T))
3048
- {
3049
- if (! __ctfe)
3050
- {
3051
- static if (swap)
3052
- return EndianSwapper! T(swapEndian(val)).array;
3053
- else
3054
- return EndianSwapper! T(val).array;
3055
- }
3056
- else
3057
- {
3058
- // Can't use EndianSwapper in CTFE.
3059
- static if (swap)
3060
- return ctfeBytes (swapEndian(val));
3061
- else
3062
- return ctfeBytes (val);
3063
- }
3064
- }
3065
-
3066
3002
@safe unittest
3067
3003
{
3068
3004
import std.meta ;
@@ -3149,13 +3085,25 @@ if (__traits(isIntegral, T))
3149
3085
because the FPU will mess up any swapped floating point values. So, you
3150
3086
can't actually have swapped floating point values as floating point values).
3151
3087
+/
3152
- T bigEndianToNative (T, size_t n)(ubyte [n] val) @safe pure nothrow @nogc
3088
+ T bigEndianToNative (T, size_t n)(ubyte [n] val) @trusted pure nothrow @nogc
3153
3089
if (canSwapEndianness! T && n == T.sizeof)
3154
3090
{
3155
- version (LittleEndian )
3156
- return endianToNativeImpl! (true , T, n)(val);
3091
+ static if (isFloatOrDouble! T)
3092
+ {
3093
+ auto retval = bigEndianToNative! (UnsignedOfSize! (T.sizeof))(val);
3094
+ return * cast (const T* ) &retval;
3095
+ }
3157
3096
else
3158
- return endianToNativeImpl! (false , T, n)(val);
3097
+ {
3098
+ enum len = T.sizeof;
3099
+ alias U = UnsignedOfSize! len;
3100
+ U retval;
3101
+
3102
+ static foreach (i; 0 .. len)
3103
+ retval |= (cast (U) val[i]) << (len - i - 1 ) * 8 ;
3104
+
3105
+ return cast (T) retval;
3106
+ }
3159
3107
}
3160
3108
3161
3109
// /
@@ -3179,13 +3127,21 @@ if (canSwapEndianness!T && n == T.sizeof)
3179
3127
because the FPU will mess up any swapped floating point values. So, you
3180
3128
can't actually have swapped floating point values as floating point values).
3181
3129
+/
3182
- auto nativeToLittleEndian (T)(const T val) @safe pure nothrow @nogc
3130
+ auto nativeToLittleEndian (T)(const T val) @trusted pure nothrow @nogc
3183
3131
if (canSwapEndianness! T)
3184
3132
{
3185
- version ( BigEndian )
3186
- return nativeToEndianImpl ! true ( val);
3133
+ static if (isFloatOrDouble ! T )
3134
+ return nativeToLittleEndian ( * cast ( const UnsignedOfSize ! (T.sizeof) * ) & val);
3187
3135
else
3188
- return nativeToEndianImpl! false (val);
3136
+ {
3137
+ enum len = T.sizeof;
3138
+ ubyte [len] retval;
3139
+
3140
+ static foreach (i; 0 .. len)
3141
+ retval[i] = cast (ubyte )(val >> i * 8 );
3142
+
3143
+ return retval;
3144
+ }
3189
3145
}
3190
3146
3191
3147
// /
@@ -3195,9 +3151,21 @@ if (canSwapEndianness!T)
3195
3151
ubyte [4 ] swappedI = nativeToLittleEndian(i);
3196
3152
assert (i == littleEndianToNative! int (swappedI));
3197
3153
3154
+ float f = 123.45f ;
3155
+ ubyte [4 ] swappedF = nativeToLittleEndian(f);
3156
+ assert (f == littleEndianToNative! float (swappedF));
3157
+
3158
+ const float cf = 123.45f ;
3159
+ ubyte [4 ] swappedCF = nativeToLittleEndian(cf);
3160
+ assert (cf == littleEndianToNative! float (swappedCF));
3161
+
3198
3162
double d = 123.45 ;
3199
3163
ubyte [8 ] swappedD = nativeToLittleEndian(d);
3200
3164
assert (d == littleEndianToNative! double (swappedD));
3165
+
3166
+ const double cd = 123.45 ;
3167
+ ubyte [8 ] swappedCD = nativeToLittleEndian(cd);
3168
+ assert (cd == littleEndianToNative! double (swappedCD));
3201
3169
}
3202
3170
3203
3171
@safe unittest
@@ -3259,13 +3227,25 @@ if (canSwapEndianness!T)
3259
3227
and therefore could vary from machine to machine (which could make it
3260
3228
unusable if you tried to transfer it to another machine).
3261
3229
+/
3262
- T littleEndianToNative (T, size_t n)(ubyte [n] val) @safe pure nothrow @nogc
3230
+ T littleEndianToNative (T, size_t n)(ubyte [n] val) @trusted pure nothrow @nogc
3263
3231
if (canSwapEndianness! T && n == T.sizeof)
3264
3232
{
3265
- version (BigEndian )
3266
- return endianToNativeImpl! (true , T, n)(val);
3233
+ static if (isFloatOrDouble! T)
3234
+ {
3235
+ auto retval = littleEndianToNative! (UnsignedOfSize! (T.sizeof))(val);
3236
+ return * cast (const T* ) &retval;
3237
+ }
3267
3238
else
3268
- return endianToNativeImpl! (false , T, n)(val);
3239
+ {
3240
+ enum len = T.sizeof;
3241
+ alias U = UnsignedOfSize! len;
3242
+ U retval;
3243
+
3244
+ static foreach (i; 0 .. len)
3245
+ retval |= (cast (U) val[i]) << i * 8 ;
3246
+
3247
+ return cast (T) retval;
3248
+ }
3269
3249
}
3270
3250
3271
3251
// /
@@ -3280,70 +3260,6 @@ if (canSwapEndianness!T && n == T.sizeof)
3280
3260
assert (c == littleEndianToNative! dchar (swappedC));
3281
3261
}
3282
3262
3283
- private T endianToNativeImpl (bool swap, T, size_t n)(ubyte [n] val) @nogc nothrow pure @trusted
3284
- if (__traits(isIntegral, T) && n == T.sizeof)
3285
- {
3286
- if (! __ctfe)
3287
- {
3288
- EndianSwapper! T es = { array: val };
3289
- static if (swap)
3290
- return swapEndian (es.value);
3291
- else
3292
- return es.value;
3293
- }
3294
- else
3295
- {
3296
- static if (swap)
3297
- return swapEndian (ctfeRead! T(val));
3298
- else
3299
- return ctfeRead! T(val);
3300
- }
3301
- }
3302
-
3303
- private auto nativeToEndianImpl (bool swap, T)(const T val) @trusted pure nothrow @nogc
3304
- if (isFloatOrDouble! T)
3305
- {
3306
- if (! __ctfe)
3307
- {
3308
- EndianSwapper! T es = EndianSwapper! T(val);
3309
- static if (swap)
3310
- es.intValue = swapEndian(es.intValue);
3311
- return es.array;
3312
- }
3313
- else
3314
- {
3315
- static if (T.sizeof == 4 )
3316
- uint intValue = * cast (const uint * ) &val;
3317
- else static if (T.sizeof == 8 )
3318
- ulong intValue = * cast (const ulong * ) & val;
3319
- static if (swap)
3320
- intValue = swapEndian(intValue);
3321
- return ctfeBytes (intValue);
3322
- }
3323
- }
3324
-
3325
- private auto endianToNativeImpl (bool swap, T, size_t n)(ubyte [n] val) @trusted pure nothrow @nogc
3326
- if (isFloatOrDouble! T && n == T.sizeof)
3327
- {
3328
- if (! __ctfe)
3329
- {
3330
- EndianSwapper! T es = { array: val };
3331
- static if (swap)
3332
- es.intValue = swapEndian(es.intValue);
3333
- return es.value;
3334
- }
3335
- else
3336
- {
3337
- static if (n == 4 )
3338
- uint x = ctfeRead! uint (val);
3339
- else static if (n == 8 )
3340
- ulong x = ctfeRead! ulong (val);
3341
- static if (swap)
3342
- x = swapEndian(x);
3343
- return * cast (T* ) &x;
3344
- }
3345
- }
3346
-
3347
3263
private template isFloatOrDouble (T)
3348
3264
{
3349
3265
enum isFloatOrDouble = isFloatingPoint! T &&
@@ -3405,6 +3321,42 @@ private template canSwapEndianness(T)
3405
3321
}
3406
3322
}
3407
3323
3324
+ private template UnsignedOfSize (size_t n)
3325
+ {
3326
+ static if (n == 8 )
3327
+ alias UnsignedOfSize = ulong ;
3328
+ else static if (n == 4 )
3329
+ alias UnsignedOfSize = uint ;
3330
+ else static if (n == 2 )
3331
+ alias UnsignedOfSize = ushort ;
3332
+ else static if (n == 1 )
3333
+ alias UnsignedOfSize = ubyte ;
3334
+ else
3335
+ alias UnsignedOfSize = void ;
3336
+ }
3337
+
3338
+ @safe unittest
3339
+ {
3340
+ static assert (is (UnsignedOfSize! (byte .sizeof) == ubyte ));
3341
+ static assert (is (UnsignedOfSize! (ubyte .sizeof) == ubyte ));
3342
+ static assert (is (UnsignedOfSize! (short .sizeof) == ushort ));
3343
+ static assert (is (UnsignedOfSize! (ushort .sizeof) == ushort ));
3344
+ static assert (is (UnsignedOfSize! (int .sizeof) == uint ));
3345
+ static assert (is (UnsignedOfSize! (uint .sizeof) == uint ));
3346
+ static assert (is (UnsignedOfSize! (long .sizeof) == ulong ));
3347
+ static assert (is (UnsignedOfSize! (ulong .sizeof) == ulong ));
3348
+
3349
+ static assert (is (UnsignedOfSize! (bool .sizeof) == ubyte ));
3350
+ static assert (is (UnsignedOfSize! (char .sizeof) == ubyte ));
3351
+ static assert (is (UnsignedOfSize! (wchar .sizeof) == ushort ));
3352
+ static assert (is (UnsignedOfSize! (dchar .sizeof) == uint ));
3353
+
3354
+ static assert (is (UnsignedOfSize! (float .sizeof) == uint ));
3355
+ static assert (is (UnsignedOfSize! (double .sizeof) == ulong ));
3356
+
3357
+ static assert (is (UnsignedOfSize! 10 == void ));
3358
+ }
3359
+
3408
3360
/+ +
3409
3361
Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
3410
3362
`T`. The value returned is converted from the given endianness to the
0 commit comments