[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Orekit Developers] JPL ephemerides files endianness detection



On 03/31/2012 05:51 PM, MAISONOBE Luc wrote:
> Hello,
> 
> I am currently cleaning up code, removing checkstyle, findbugs and
> javadoc warnings. In the process, I noticed the following problem.
> 
> The latest JPL ephemerides loader class includes a binary file
> endianness detection, which I think was ported from calceph. Detection
> is based on the following statement:
> 
> // simple heuristic: if the read value is larger than half the range of
> an integer
> //                 assume the file is in little-endian format
> if ((deNum & 0xffffffffL) > (1 << 15)) {
>      bigEndian = false;
> }
> 
> where deNum is an int.
> 
> Findbugs complains about the test, it consider it is a "Check for sign
> of bitwise operation", explained here:
> <http://findbugs.sourceforge.net/bugDescriptions.html#BIT_SIGNED_CHECK>.
> 
> I think that we could get rid of the error by removing the bit mask in
> the test as follows:
> 
> if (deNum > (1 << 15)) {
>      bigEndian = false;
> }
> 
> Since deNum is an int and Java ints are known to be 32 bits, I think the
> mask does not serve any purpose. I didn't look at calceph code, but
> think such a test is useful when using uint64 C type or similar.
> 
> Does anybody has an opinion about this ?

Hi Luc,

I think the test is necessary, as java does not have an unsigned int
data type. For values that are read in the wrong byte order and happen
to be negative, the test will fail otherwise, see my example below:

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class EndianTest {

    public static void main(String[] args) {
        ByteBuffer bb = ByteBuffer.allocate(4);
        bb.order(ByteOrder.LITTLE_ENDIAN);

        bb.putInt(400);

        byte[] littleArr = bb.array();

        bb = ByteBuffer.allocate(4);
        bb.order(ByteOrder.BIG_ENDIAN);

        bb.mark();
        bb.put(littleArr);
        bb.reset();

        int i = bb.getInt();
        boolean test1 = (i > (1 << 15));
        boolean test2 = (i & 0xffffffffL) > (1 << 15);
        System.out.println(i + " test1=" + test1 + " test2=" + test2);
    }
}

There are surely better ways to test for endianess, I will have to
investigate a bit.

Thomas