Matthew,
To give another example:
var_dump(array(sprintf('%u', ip2long('127.0.0.1')) => 'foo',
sprintf('%u',
ip2long('255.255.255.0')) => 'bar'));
array(2) {
[2130706433]=>
string(3) "foo"
["4294967040"]=>
string(3) "bar"
}
The keys are now two different types (string vs int) on 32-bit platforms,
which leads to problems with strict comparison.
Another issue is persistence - if you save these to unsigned integer
columns in database, and your data access layer converts them back to
integers on load, the values are going to change again depending on what
platform you're on.
To quote the specific case where I encountered this, I have an audit trail
system that logs a lot of user activity - as an optimization, I hash and
store certain keys using crc32() numeric values, since storing a 32-bit
number is much cheaper (in terms of storage) than storing strings, as well
as giving much faster queries.
I encountered all of the problems mentioned while debugging an error in
this system, and it seems completely bonkers to have to spend this much
time on something that ought to be totally trivial, and would have been, if
these functions returned consistent results on all platforms.
Why would you consider a consistent function "crippled"?
Look at the sheer number of comments on the crc32 manual page and tell me
if you still think this works well for anybody... many of the comments
(including mine!) aren't even correct and don't lead to predictable
results...
This should be easy but it is extremely hard.
In my opinion, the function is "crippled" as it is...
On Fri, Aug 30, 2013 at 12:27 PM, Matthew Leverton <[email protected]>wrote:
> On Fri, Aug 30, 2013 at 10:29 AM, Rasmus Schultz <[email protected]>
> wrote:
> > No replies probably means no one cares. oh well.
> >
> > For the record, the examples I posted are wrong - the correct way to
> > convert the long values consistently appears to be:
> >
> > list($v) = array_values(unpack('l', pack('l',
> ip2long('255.255.255.0'))));
> >
> I had spotted the error, but didn't want to reply because I don't
> really understand what you are getting at.
>
> The core issue is that PHP doesn't provide a 32-bit unsigned integer
> on a 32-bit platform ... and/or that the size of integer changes
> depending on the platform. But I doubt that is going to change any
> time soon. Crippling 64-bit systems due to old, legacy 32-bit
> platforms is shortsighted.
>
> What's wrong with the manual's approach?
>
> $checksum = sprintf("%u", crc32("The quick brown fox jumped over the
> lazy dog."));
>
> Are you going to do further mathematical operations on it? You can
> take that string and stuff it into an uint32 field into a db without
> an issue.
>
> At the end of the day, there's no getting around that PHP programmers
> need to be aware of the difference between 32-bit and 64-bit systems
> ... it affects far more than these two particular functions.
>
> But if these two functions are particularly bothersome, a better "fix"
> IMO is just:
>
> $crc = crc32("12341234", CRC32_UINT32_STRING);
>
> Where the second parameter is CRC32_INT (default & current behavior),
> CRC32_INT32 (always negative if high bit is set), CRC32_UINT32_STRING,
> CRC32_HEX_STRING
>
> Forgive the poor names.
>
> --
> Matthew Leverton
>