www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Endianness - How to test code for portability

reply Preetpal <preetpal.sohal gmail.com> writes:
In the portability section of the language spec, they talk about 
endianness (https://dlang.org/spec/portability.html#endianness)  
which refers "to the order in which multibyte types are stored." 
IMO if you wanted to actually be sure your code is portable 
across both big endian and little endian systems, you should 
actually run your code on both types of systems and test if there 
any issues.

The problem is that I am not aware of any big-endian systems that 
you can actually test on and if there is any D lang compiler 
support for any of these systems if they exist.

This is not an important issue to me but I was just curious to 
see if anyone actually tests for portability issues related to 
endianness by compiling their D Lang code for a big endian 
architecture and actually running it on that system.
Mar 11 2021
next sibling parent reply Dennis <dkorpel gmail.com> writes:
On Friday, 12 March 2021 at 05:53:40 UTC, Preetpal wrote:
 This is not an important issue to me but I was just curious to 
 see if anyone actually tests for portability issues related to 
 endianness by compiling their D Lang code for a big endian 
 architecture and actually running it on that system.
I have a png decoder, and I often avoid a dependency on endianness by using bit-shifts instead of casts. For example, this code reads a big-endian integer and returns a native-endian integer, regardless of architecture: ``` uint readUintBe(in ubyte[] s) { return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; } ``` There is a part in the decompression where a ubyte[] is cast to a uint[] for performance, and it assumes a little-endian byte order. There is a fallback for big-endian architectures, but also for CTFE, where reinterpretation through overlapped fields or array casts is not allowed. So the code is structured like this: ``` version(BigEndian) { private enum bigEndian = true; } else { private enum bigEndian = false; } int parse(in ubyte[] data) { if (__ctfe || bigEndian) { // Portable code } else { // Little-endian optimized code } } ``` Then you can test both at runtime and compile time: ``` unittest { ubyte[] testData = [...]; assert(parse(testData) == 3); static assert(parse(testData) == 3); } ``` So no, I don't have a big-endian computer I can test it on, but I do test with CTFE, so I'm pretty sure I'm not relying on a specific byte order.
Mar 12 2021
parent Preetpal <preetpal.sohal gmail.com> writes:
On Friday, 12 March 2021 at 10:26:55 UTC, Dennis wrote:
 ```
 version(BigEndian) {
     private enum bigEndian = true;
 } else {
     private enum bigEndian = false;
 }

 int parse(in ubyte[] data) {
     if (__ctfe || bigEndian) {
         // Portable code
     } else {
         // Little-endian optimized code
     }
 }
 ```

 Then you can test both at runtime and compile time:
 ```
 unittest {
     ubyte[] testData = [...];
     assert(parse(testData) == 3);
     static assert(parse(testData) == 3);
 }
 ```

 So no, I don't have a big-endian computer I can test it on, but 
 I do test with CTFE, so I'm pretty sure I'm not relying on a 
 specific byte order.
I never even thought of using CTFE for this purpose. Using CTFE to test cases you cannot simulate using runtime testing is a really great idea.
Mar 12 2021
prev sibling parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Friday, 12 March 2021 at 05:53:40 UTC, Preetpal wrote:
 In the portability section of the language spec, they talk 
 about endianness 
 (https://dlang.org/spec/portability.html#endianness)  which 
 refers "to the order in which multibyte types are stored." IMO 
 if you wanted to actually be sure your code is portable across 
 both big endian and little endian systems, you should actually 
 run your code on both types of systems and test if there any 
 issues.

 The problem is that I am not aware of any big-endian systems 
 that you can actually test on and if there is any D lang 
 compiler support for any of these systems if they exist.

 This is not an important issue to me but I was just curious to 
 see if anyone actually tests for portability issues related to 
 endianness by compiling their D Lang code for a big endian 
 architecture and actually running it on that system.
Actual big endian systems? Not many around anymore: - SPARC almost dead - IBM z/system still around and not going away but a D implementation not very likely as it adds the other difficulty that it is not ASCII but EBCDIC. - AVR32 doesn't look very vivid. - Freescale Coldfire (as successor of 68K) also on a descending path - OpenRISC superseded by RISC-V Some CPU can do both but are generally used in little endian mode (ARM, Power) or also obsolete (Alpha, IA64). While from an intellectual perspective endiannes support is a good thing, from a pure pragmatic vue it is a solved issue. Little endian won, definitely (except on the network in the TCP/IP headers).
Mar 13 2021