{
Copyright (C) 1998-99 Free Software Foundation, Inc.

Author: Frank Heckenbach <frank@pascal.gnu.de>

Routines to handle endianness.

This file is part of GNU Pascal Library. The GNU Pascal Library is free
software; you can redistribute it and/or modify it under the terms of
the GNU Library General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.

The GNU Pascal Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with the GNU Pascal Library; see the file COPYING.LIB.  If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
}

unit Endian;

interface

(*@@fjf252.pas*)type sizetype=cardinal;

{ Boolean constants about endianness and alignment }

const
  Bits_Big_Endian  = {$ifdef __BITS_LITTLE_ENDIAN__} False
                     {$else}{$ifdef __BITS_BIG_ENDIAN__} True
                     {$else}{$error Bit endianness is not defined!}
                     {$endif}{$endif};

  Bytes_Big_Endian = {$ifdef __BYTES_LITTLE_ENDIAN__} False
                     {$else}{$ifdef __BYTES_BIG_ENDIAN__} True
                     {$else}{$error Byte endianness is not defined!}
                     {$endif}{$endif};

  Words_Big_Endian = {$ifdef __WORDS_LITTLE_ENDIAN__} False
                     {$else}{$ifdef __WORDS_BIG_ENDIAN__} True
                     {$else}{$error Word endianness is not defined!}
                     {$endif}{$endif};

  Need_Alignment   = {$ifdef __NEED_ALIGNMENT__} True
                     {$else} False {$endif};

{ Convert single variables from or to little or big endian format.
  For structures, this has to be done for each component separately!
  Currently, ConvertFromFooEndian and ConvertToFooEndian are the same, but
  this might not be the case on middle-endian machines. So it's better to
  provide and use different names. }
procedure ReverseBytes            (var Buf; Count : SizeType);                                asmname '_p_reversebytes';
procedure ConvertFromLittleEndian (var Buf; Count : SizeType);                                asmname '_p_convertlittleendian';
procedure ConvertFromBigEndian    (var Buf; Count : SizeType);                                asmname '_p_convertbigendian';
procedure ConvertToLittleEndian   (var Buf; Count : SizeType);                                asmname '_p_convertlittleendian';
procedure ConvertToBigEndian      (var Buf; Count : SizeType);                                asmname '_p_convertbigendian';

{ Combine the conversion with file block routines }
function  BlockReadLittleEndian   (var aFile : File; var   Buf; Count : SizeType) : SizeType; asmname '_p_blockread_littleendian';
function  BlockReadBigEndian      (var aFile : File; var   Buf; Count : SizeType) : SizeType; asmname '_p_blockread_bigendian';
function  BlockWriteLittleEndian  (var aFile : File; const Buf; Count : SizeType) : SizeType; asmname '_p_blockwrite_littleendian';
function  BlockWriteBigEndian     (var aFile : File; const Buf; Count : SizeType) : SizeType; asmname '_p_blockwrite_bigendian';

implementation

(*$W-*) (*@@fjf234c.pas*)

{$I-,B-} { I/O errors are passed back to the caller }

procedure ReverseBytes (var Buf; Count : SizeType);
var
  i : SizeType;
  b : Byte;
  ByteBuf : array [1 .. Count] of Byte absolute Buf;
begin
  for i := 1 to Count div 2 do
    begin
      b := ByteBuf [i];
      ByteBuf [i] := ByteBuf [Count + 1 - i];
      ByteBuf [Count + 1 - i] := b
    end
end;

procedure ConvertFromLittleEndian (var Buf; Count : SizeType);
begin
  if Bytes_Big_Endian then ReverseBytes (Buf, Count)
end;

procedure ConvertFromBigEndian (var Buf; Count : SizeType);
begin
  if not Bytes_Big_Endian then ReverseBytes (Buf, Count)
end;

function  BlockReadLittleEndian (var aFile : File; var Buf; Count : SizeType) = Result : SizeType;
begin
  BlockRead (aFile, Buf, Count, Result);
  if InOutRes = 0 then ConvertFromLittleEndian (Buf, Count)
end;

function  BlockReadBigEndian (var aFile : File; var Buf; Count : SizeType) = Result : SizeType;
begin
  BlockRead (aFile, Buf, Count, Result);
  if InOutRes = 0 then ConvertFromBigEndian (Buf, Count)
end;

function  BlockWriteLittleEndian (var aFile : File; const Buf; Count : SizeType) = Result : SizeType;
var TempBuf : array [1..Count] of Byte;
begin
  Move (Buf, TempBuf, Count);
  ConvertToLittleEndian (TempBuf, Count);
  BlockWrite (aFile, TempBuf, Count, Result)
end;

function  BlockWriteBigEndian (var aFile : File; const Buf; Count : SizeType) = Result : SizeType;
var TempBuf : array [1..Count] of Byte;
begin
  Move (Buf, TempBuf, Count);
  ConvertToBigEndian (TempBuf, Count);
  BlockWrite (aFile, TempBuf, Count, Result)
end;

end.
