I had a situation where I had to unpack a file filled with little-endian order double-floats in a way that would work on either little-endian or big-endian machines. PHP doesn't have a formatting code that will change the byte order of doubles, so I wrote this workaround.
<?php
function big_endian_unpack ($format, $data) {
$ar = unpack ($format, $data);
$vals = array_values ($ar);
$f = explode ('/', $format);
$i = 0;
foreach ($f as $f_k => $f_v) {
$repeater = intval (substr ($f_v, 1));
if ($repeater == 0) $repeater = 1;
if ($f_v{1} == '*')
{
$repeater = count ($ar) - $i;
}
if ($f_v{0} != 'd') { $i += $repeater; continue; }
$j = $i + $repeater;
for ($a = $i; $a < $j; ++$a)
{
$p = pack ('d',$vals[$i]);
$p = strrev ($p);
list ($vals[$i]) = array_values (unpack ('d1d', $p));
++$i;
}
}
$a = 0;
foreach ($ar as $ar_k => $ar_v) {
$ar[$ar_k] = $vals[$a];
++$a;
}
return $ar;
}
list ($endiantest) = array_values (unpack ('L1L', pack ('V',1)));
if ($endiantest != 1) define ('BIG_ENDIAN_MACHINE',1);
if (defined ('BIG_ENDIAN_MACHINE')) $unpack_workaround = 'big_endian_unpack';
else $unpack_workaround = 'unpack';
?>
This workaround is used like this:
<?php
function foo() {
global $unpack_workaround;
$bar = $unpack_workaround('N7N/V2V/d8d',$my_data);
}
?>
On a little endian machine, $unpack_workaround will simply point to the function unpack. On a big endian machine, it will call the workaround function.
Note, this solution only works for doubles. In my project I had no need to check for single precision floats.