Compound data type

From Rosetta Code
Revision as of 23:41, 25 February 2007 by rosettacode>Sgeier (-> Removed Tcl since the task has changed. Thhis can probably somehow be faked in Tcl, but it would be completely pointless.)
Task
Compound data type
You are encouraged to solve this task according to the task description, using any language you may know.

Task 1: Create a structure Point(int x, int y)

 - Its internal content is in byte machine format (C struct) compatible.
 - For instance, by using pack/unpack internally on some scripting language. 
 - For a given object point with x=1 and y=2,
   the byte stream should be on x86 32-bit machines: 
   [0x01 0x00 0x00 0x00 | 0x02 0x00 0x00 0x00]

Task 2: Create a structure MyData as described in ANSI C as follows:

 #pragma pack(1)
 typedef struct MyData
 {
   signed char         m_sch;      //  8-bit signed
   unsigned char       m_uch;      //  8-bit unsigned
   signed short        m_ss;       // 16-bit signed
   unsigned short      m_us;       // 16-bit unsigned
   signed long         m_sl;       // 32-bit signed
   unsigned long       m_ul;       // 32-bit unsigned
   signed long long    m_sll;      // 64-bit signed
   unsigned long long  m_ull;      // 64-bit unsigned
   signed int          m_si;       // register int signed (native)
   unsigned int        m_ui;       // register int unsigned (native)
   float               m_f;        // 32-bit floating point
   double              m_d;        // 64-bit floating point
   long double         m_ld;       // 80-bit or 128-bit floating point
   char                m_str[80];  // 80 bytes ANSI string
   wchar_t             m_wstr[80]; // 80 wchar string (not sure if its UTF-16)
 } MyData;
 MyData foo = { -12, +12, -23456, +23456, -12345678, +12345678, -1234567890, +1234567890,
                  1, 2, 3.14159, 6.28318, 9.42477, "Hello world!", L"Hello world!" };

Ada

Compiler: GNAT GPL 2006

Task 1

type Point is record
   X : Integer := 0;
   Y : Integer := 0;
end record;

Task 2

type Unsigned_8 is mod 2**8;
type Unsigned_16 is mod 2**16;
type Unsigned_32 is mod 2**32;
type Unsigned_64 is mod 2**64;
type Signed_8 is range -128..127;
type Signed_16 is range -(2**15)..(2**15 - 1);
type Signed_32 is range -(2**31)..(2**31 - 1);
type Signed_64 is range -(2**63)..(2**63 - 1);
type My_Data is record
   M_sch  : Signed_8;
   M_uch  : Unsigned_8;
   M_ss   : Signed_16;
   M_us   : Unsigned_16;
   M_sl   : Signed_32;
   M_ul   : Unsigned_32;
   M_sll  : Signed_64;
   M_ull  : Unsigned_63;
   M_si   : Integer;
   M_ui   : Unsigned_32;
   M_f    : Float;
   M_d    : Long_Float;
   M_ld   : Long_Long_Float;
   M_Str  : String(1..80);
   M_Wstr : Wide_String(1..80);
end record;

The Ada pragma Pack will compress the data, but may re-arrange the fields in memory. The only way to ensure a particular memory layout is to provide a representation clause. The representation clause allows the storage specification down to the bit level.

Word : constant := 4; -- storage element is byte, four elements per word
for My_Data use record
   M_sch at 0 * Word range 0..7;
   M_uch at 0 * Word range 8..15;
   M_ss  at 0 * Word range 16..31;
   M_us  at 1 * Word range 0..15;
   M_sl  at 1 * Word range 16..47;
   M_ul  at 2 * Word range 16..47;
   M_sll at 3 * Word range 16..79;
   M_ull at 5 * Word range 16..79;
   M_si  at 7 * Word range 16..47;
   M_ui  at 8 * Word range 16..47;
   M_F   at 9 * Word range 16..49;
   M_D   at 10 * Word range 18..81;
   M_Ld  at 12 * Word range 18..113; -- 96 bytes minimum
   M_Str at 15 * Word range 18..657;
   M_Wstr at 35 * Word range 18..1297;
end record;

BASIC

Interpeter: QuickBasic 4.5, PB 7.1

TYPE Point
  x AS INTEGER
  y AS INTEGER
END TYPE

C

Compiler: GCC, MSVC, BCC, Watcom

Libraries: Standard

 typedef struct Point
 {
   int x;
   int y;
 } Point;

C++

Compiler: GCC, Visual C++, BCC, Watcom

 // C++ style: typedef is not required
 struct Point
 {
   int x;
   int y;
 };
 // C style
 typedef struct Point
 {
   int x;
   int y;
 } Point;

C#

 // Implicit: [StructLayout(LayoutKind.Sequential, Pack = 1)]
 struct Point
 {
   public int x, y;
   public Point() { x = 0; y = 0; }
   public Point(int x0) { x = x0; y = 0; }
   public Point(int x0, int y0) { x = x0; y = y0; }
 }
 // Verbose version
 .class public sequential ansi sealed beforefieldinit Point
 extends [mscorlib]System.ValueType
 {
   public int x, y;
   public Point() { x = 0; y = 0; }
   public Point(int x0) { x = x0; y = 0; }
   public Point(int x0, int y0) { x = x0; y = y0; }
 }
 public static Point ReadFromFileStream(FileStream fs)
 {
   // Create a buffer
   byte[] buffer = new byte[Marshal.SizeOf(typeof(Point))]; 
   // Read bytes into the buffer...
   fs.Read(buffer, 0, Marshal.SizeOf(typeof(Point)) );
   // Make sure that the Garbage Collector does not move the buffer 
   GCHandle handle = GCHandle.Alloc(buff, GCHandleType.Pinned);
   // Marshal the bytes
   Point point = (Point)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Point)); 
   // Give control of the buffer back to the Garbage Collector 
   handle.Free(); 
   return point;
 }
 public static Point ReadFromBinaryReader(BinaryReader br)
 {
   //Read byte array
   byte[] buffer = br.ReadBytes(Marshal.SizeOf(typeof(Point)));
   //Make sure that the Garbage Collector doesn't move our buffer 
   GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
   //Marshal the bytes
   Point point = (Point)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Point));
   // Give control of the buffer back to the Garbage Collector 
   handle.Free(); 
   return point;
 }
 // Improve speed by using PointSize
 internal sealed class PointSize
 {
   public static int size;
   static PointSize()
   {
     size = Marshal.SizeOf(typeof(Point));
   }
   public static int Size
   {
     get
     {
       return size;
     }
   }
 }

D TODO

Compiler: DMD,GDC

Forth TODO

Fortran TODO


Java TODO

// The byte structure format does not exist natively --> TODO.
public class Point
{
  public int x, y;
  public Point() { this(0); }
  public Point(int x0) { this(x0,0); }
  public Point(int x0, int y0) { x = x0; y = y0; }
  public static void main(String args[])
  {
    Point point = new Point(1,2);
    System.out.println("x = " + point.x );
    System.out.println("y = " + point.y );
  }
}

JavaScript TODO

 var point = new Object();
 point.x = 1;
 point.y = 2;

JSON TODO

 var point = {
   x:1,
   y:2
 };

Perl TODO

Interpeter: Perl

 # Please verify the code above... (from CPAN docs, not tested)
 # Using Inline::Struct with C code embedded
 use Inline C;
 my $point = new Inline::Struct::Point(1,2);
 
 __C__
 typedef struct Point 
 {
   int x;
   int y;
 };
 # Using Inline C, Struct
 use Inline C => <<'END', ENABLE => 'STRUCTS';
 struct Point {
   int x;
   int y;
 };
 END

 my $point = Inline::Struct::Point->new(1,2);
 print $point->x, $point->y, "\n";
 # Using bytes packed data with pack/unpack
 my $point = pack("ii", 1, 2);
 my ($x, $y) = unpack("ii", $point);
 # Using Win32::API::Struct
 use Win32::API;
 Win32::API::Struct->typedef( 'Point', qw(
   int x;
   int y;
 ));
 # Declarative
 my $point = new Win32::API::Struct->new( 'Point' );
 $point->{x} = 1;
 $point->{y} = 2;
 # Tie
 tie %point, 'Win32::API::Struct', 'Point';
 $point{x} = 1;
 $point{y} = 2;


 # Using C::DynaLib::Struct
 use C::DynaLib::Struct;
 Define C::DynaLib::Struct('Point', 'ii', [qw(x y)]);  
 # Using C::Include
 use C::Include qw(point.h -cache);
 my $point = $include->make_struct( 'Point' );
 point.h:
 #ifdef __PERL__
 // Anything that should be parsed by C::Include only
 #endif
 typedef struct Point { int x; int y; } Point;


 ### The code below does not create a "binary" like structure.
 # Using Class::Struct
 use Class::Struct;
 struct Point => [ x => '$', y => '$' ];
 my $point = new Point( x => 1, y => 2 );
 # Using a hash for storage
 my %point = ( x => 1, y => 2);

PHP TODO

 # Using pack/unpack 
 $point = pack("ii", 1, 2);
 $u = unpack("ix/iy", $point);
 echo $x;
 echo $y;
 list($x,$y) = unpack("ii", $point);
 echo $x;
 echo $y;

OCaml TODO

 type json point = < x: int; y: int >