Re: [PECL-DEV] Endianness in PHP

[email protected] (Melanie Rhianna Lewis)
Newsgroups php.pecl.dev
Message-ID <[email protected]>
Hi there,

On 12 Aug 2010, at 06:43, J. Adams wrote:

> Thanks for your response Alexey. I am aware of those functions but am really wondering if they are the way this is usually handled in PHP.  The function htonl appears in the PHP Trunk in only about 10 places:
> http://lxr.php.net/search?q=htonl&project=PHP_TRUNK&defs=&refs=&path=&hist=
> 
> My concerns are mostly about portability (see below).
>>> Two questions:
>>> 1) Is there a standardized way or recommended best practice for conversions
>>> of ints, longs, and doubles to network byte order?
>>> 
>> 
>> Usually, operating system provides functions for this.
>> Look for the following functions: htonl, htons, ntohl, ntohs
>> 
> It's my understanding that these functions aren't always available.  This link:
> http://www.codeguru.com/forum/showthread.php?t=298741
> says "'ntohs()', 'ntohl()', 'htons()', and 'htonl()' are not part of the C standard, and thus do not guarentee [sic] portability. "
> 
> Also, my linux man pages say "These routines convert 16 and 32 bit quantities between network byte order and host byte order."  Correct me if I'm wrong, but, PHP appears to use long rather than more specific data types like uint32_t.  What happens when a long is 64 bits? Are these conversions valid for signed quantities?  The docs all suggest they are for unsigned 16- or 32-bit ints. What about longs? What about doubles?
> 
> I'm also wondering about the includes required for these functions.  On *nix machines, it would appear to be:
> #include <arpa/inet.h>
> On windows, it would seem to be:
> #include <winsock2.h>
> Would that cover every platform where PHP is supposed to run?
> 
> Seems to me PHP needs some standard way of handling this issue. If you insist these functions are the way to go, I will believe you, but that solution seems incomplete to me.


htonl etc. are not ANSI but are POSIX which means they should be supported by all platforms that are POSIX compliant.  (I know this doesn't mean much since POSIX compliance can be variable).  You can detect POSIX compliance with one of many __POSIX_???? defines (check the headers).  Windows is now supposed to be compliant to some level so may even support the standard header.  I've not got a windows dev environment to hand to check.   However that doesn't really help you for doubles, floats etc.

ANSI C99 defines standard sizes/types in stdint.h.  Unfortunately a long is defined as "at least 4 bytes" so an 64 bit int could be a long or a long long.  However sometimes the __WORDSIZE macro is defined with values 32 or 64 as appropriate.  You could just detect using:

is64bit = (sizeof(long) == 8);

You can easily detect endianness as follows:

Either:

int test = 1;
littleEndian = *((unsigned char*)&test);

Or the rather neat;

littleEndian = ((int*)"BAA") | 1;

It would be nice if such macros were added to the core to be available for more than one extension.

The last time I had to do something like serialization in a defined endian I ended up writing the code from scratch.  It is best to serialize in to a byte buffer.

Sorry but there's no clean way.  However all those platforms that support GCC will have had a lot of this done by GCC itself.

If you want some testing done on different endians I can help there.

Melanie
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.