Converting big-endian signed 16bits values to fpc integer

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Converting big-endian signed 16bits values to fpc integer

Giuliano Colla
I'm dealing with a large number of data coming from an external device.
They are big-endian 16 bits signed numbers, which must be converted to
integer and to real to perform calculations.

Besides the obvious solutions of treating them as isolated bytes,
multipying by 256 the highest, adding the lower, and oring wit
$FFFF0000, or whatever sizeof(Integer) suggests if the result is bigger
than 32767, is there a more efficient and elegant way to achieve the result?

I'm a bit lost on all available data types, and unable to tell apart the
ones which are platform specific and the ones which are not, which
assignments give the proper result and which do not.

Any suggestion would be greatly appreciated.

Giuliano Colla



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Converting big-endian signed 16bits values to fpc integer

Jeppe Græsdal Johansen
Just use the BEtoN function. That will convert whatever big-endian
number to your native endian.

I don't know what speed it has, but it sure is elegant :)

Den 16-04-2012 00:38, Giuliano Colla skrev:

> I'm dealing with a large number of data coming from an external device.
> They are big-endian 16 bits signed numbers, which must be converted to
> integer and to real to perform calculations.
>
> Besides the obvious solutions of treating them as isolated bytes,
> multipying by 256 the highest, adding the lower, and oring wit
> $FFFF0000, or whatever sizeof(Integer) suggests if the result is
> bigger than 32767, is there a more efficient and elegant way to
> achieve the result?
>
> I'm a bit lost on all available data types, and unable to tell apart
> the ones which are platform specific and the ones which are not, which
> assignments give the proper result and which do not.
>
> Any suggestion would be greatly appreciated.
>
> Giuliano Colla
>
>
>
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Converting big-endian signed 16bits values to fpc integer

Jonas Maebe-2
In reply to this post by Giuliano Colla

On 16 Apr 2012, at 00:38, Giuliano Colla wrote:

> I'm dealing with a large number of data coming from an external device.
> They are big-endian 16 bits signed numbers, which must be converted to integer and to real to perform calculations.
>
> Besides the obvious solutions of treating them as isolated bytes, multipying by 256 the highest, adding the lower, and oring wit $FFFF0000, or whatever sizeof(Integer) suggests if the result is bigger than 32767, is there a more efficient and elegant way to achieve the result?

Call BEtoN() on them (Big Endian to Native byte order). Note that this routine is overloaded for all integer sizes > 1, and that FPC extends the size of any number < 32/64 bits (depending on the architecture) to 32/64 bits when performing almost any operation on it. It's therefore probably the safest to call it as BEtoN(smallint(value)) to ensure that the correct overload is selected.


Jonas_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Converting big-endian signed 16bits values to fpc integer

Giuliano Colla
Il 16/04/2012 00:42, Jonas Maebe ha scritto:
> On 16 Apr 2012, at 00:38, Giuliano Colla wrote:
>
>> I'm dealing with a large number of data coming from an external device.
>> They are big-endian 16 bits signed numbers, which must be converted to integer and to real to perform calculations.
>>
>> Besides the obvious solutions of treating them as isolated bytes, multipying by 256 the highest, adding the lower, and oring wit $FFFF0000, or whatever sizeof(Integer) suggests if the result is bigger than 32767, is there a more efficient and elegant way to achieve the result?
> Call BEtoN() on them (Big Endian to Native byte order). Note that this routine is overloaded for all integer sizes>  1, and that FPC extends the size of any number<  32/64 bits (depending on the architecture) to 32/64 bits when performing almost any operation on it. It's therefore probably the safest to call it as BEtoN(smallint(value)) to ensure that the correct overload is selected.
>
>
I was sure that hidden somewhere there was a better way!
Thanks a lot

Giuliano


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Converting big-endian signed 16bits values to fpc integer

Andrew Haines
In reply to this post by Giuliano Colla
On 04/15/12 18:38, Giuliano Colla wrote:

> I'm dealing with a large number of data coming from an external device.
> They are big-endian 16 bits signed numbers, which must be converted to
> integer and to real to perform calculations.
>
> Besides the obvious solutions of treating them as isolated bytes,
> multipying by 256 the highest, adding the lower, and oring wit
> $FFFF0000, or whatever sizeof(Integer) suggests if the result is bigger
> than 32767, is there a more efficient and elegant way to achieve the
> result?
>
> I'm a bit lost on all available data types, and unable to tell apart the
> ones which are platform specific and the ones which are not, which
> assignments give the proper result and which do not.
>
> Any suggestion would be greatly appreciated.
>
> Giuliano Colla
>
> There exists the BEtoN and LEtoN functions you can use.



There exists the BEtoN and LEtoN functions you can use. (NtoLE and NtoBE
also)

var
  Data: SmallInt; // 16 bit signed type
...
Data := GetBENumberFromWherever;
Data := BEtoN(Data);

I'm not sure about real types. If they are 32 bits and sent in two
pieces then you could just do

var
  Data: Single; // 4 bytes
  DataArray: array[0..1] of Word absolute Data;
...
// I'm not sure how the data is represented in memory for floats.
  DataArray[1] := BEtoN(Word(GetBENumberFromWherever));
  DataArray[0] := BEtoN(Word(GetBENumberFromWherever));


Anyway you get the idea. Probably you will have to experiment to achieve
exactly what you want. Someone else probably has a better answer.

Regards,

Andrew
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Converting big-endian signed 16bits values to fpc integer

Mark Morgan Lloyd-5
In reply to this post by Jonas Maebe-2
Jonas Maebe wrote:
> On 16 Apr 2012, at 00:38, Giuliano Colla wrote:
>
>> I'm dealing with a large number of data coming from an external device.
>> They are big-endian 16 bits signed numbers, which must be converted to integer and to real to perform calculations.
>>
>> Besides the obvious solutions of treating them as isolated bytes, multipying by 256 the highest, adding the lower, and oring wit $FFFF0000, or whatever sizeof(Integer) suggests if the result is bigger than 32767, is there a more efficient and elegant way to achieve the result?
>
> Call BEtoN() on them (Big Endian to Native byte order). Note that this routine is overloaded for all integer sizes > 1, and that FPC extends the size of any number < 32/64 bits (depending on the architecture) to 32/64 bits when performing almost any operation on it. It's therefore probably the safest to call it as BEtoN(smallint(value)) to ensure that the correct overload is selected.

I asked this a few weeks ago in the context of doing endianness-changes
in-place in a data structure, and Martin (I think) suggested overloading
the := operator.

I did however find that one has to be extremely careful inside the
custom operator, I ended up using Move() rather than an assignment to
the result since it was tending to go recursive- some way of inhibiting
all automatic type conversions would be useful.


(* This type represents a little-endian word, irrespective of the
platform. It  *)
(* is of known size (16 bits, tested by assertion) but is not directly
         *)
(* compatible with any other type.
         *)
//
type    WordLE= packed record b0, b1: byte; end;


(* Assign a little-endian word to an (unsigned) integer, with
appropriate       *)
(* conversion.
         *)
//
operator := (wle: WordLE): word;

begin
..

Type TAWSHeader=packed Record
        ThisSize: WordLE;
        PrevSize: WordLE;
        Flags:    Byte;
        Rsvd:     Byte;
      End;

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Converting big-endian signed 16bits values to fpc integer

Giuliano Colla
In reply to this post by Andrew Haines
Il 16/04/2012 01:44, Andrew Haines ha scritto:
>
> There exists the BEtoN and LEtoN functions you can use. (NtoLE and NtoBE
> also)
>
Thanks to everybody.
Now I believe to have enough information to proceed.
I'll keep this little piece of discussion as an example to show when
someone asks me why I prefer open source software to proprietary one!

Giuliano

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal