Recent

Author Topic: Record with different variables - better workaround?  (Read 480 times)

Paul_

  • Full Member
  • ***
  • Posts: 130
Record with different variables - better workaround?
« on: June 28, 2019, 02:56:38 pm »
My goal is to have one "unified" record (TVehicle) which can contains (passed by pointer) different types/variables (TCarParameters or TTruckParameters) like in example.
Could it be (whole structure, passing parameters etc.) somehow simplified? Thanks.

Code: Pascal  [Select]
  1. //{$mode delphi}
  2. {$mode objfpc}{$H+}
  3. {$modeswitch ADVANCEDRECORDS}
  4.  
  5. Uses crt, sysUtils;
  6.  
  7. Type
  8.   TVehicleType = ( Car , Truck );
  9.  
  10.   PCarParameters = ^TCarParameters;
  11.   TCarParameters = record
  12.     crew : Integer;
  13.   end;
  14.  
  15.   PTruckParameters = ^TTruckParameters;
  16.   TTruckParameters = record
  17.     cargo   : Integer;
  18.     trailer : Boolean;
  19.   end;
  20.  
  21.   PVehicle = ^TVehicle;
  22.   TVehicle = record
  23.     carType    : TVehicleType;
  24.     parameters : Pointer;
  25.   end;
  26.  
  27.   TVehicleDatabase = record
  28.     list       : Array [0..9] of TVehicle;
  29.     count      : Integer;
  30.  
  31.     procedure Init;
  32.     procedure AddVehicle(const _carType: TVehicleType; const _parameters: pointer); // GetMem
  33.     procedure WriteInfo(Index: Integer);
  34.     procedure Free;
  35.   end;
  36.  
  37. Var
  38.   DB : TVehicleDatabase;
  39.  
  40. procedure TVehicleDatabase.Init;
  41. begin
  42.   count := 0;
  43. end;
  44.  
  45. procedure TVehicleDatabase.AddVehicle( const _carType : TVehicleType; const _parameters : pointer );
  46. var
  47.   pT : PTruckParameters;
  48. begin
  49.   if count - 1 = high(list) then exit;
  50.  
  51.   list[count].carType := _carType;
  52.  
  53.   case list[count].carType of
  54.     // First option
  55.     car : begin
  56.       GetMem( list[count].Parameters, SizeOf(TCarParameters) );
  57.       FillChar(list[count].Parameters^, SizeOf(TCarParameters), 0);
  58.  
  59.       TCarParameters( list[count].parameters^ ).crew := TCarParameters( _parameters^ ).crew;
  60.     end;
  61.  
  62.     // Second option
  63.     truck :  begin
  64.       GetMem( list[count].Parameters, SizeOf(TTruckParameters) );
  65.       FillChar(list[count].Parameters^, SizeOf(TTruckParameters), 0);
  66.  
  67.       pT := list[count].parameters;
  68.  
  69.       pT^.cargo := TTruckParameters( _parameters^ ).cargo;
  70.       pT^.trailer := TTruckParameters( _parameters^ ).trailer;
  71.     end;
  72.   end;
  73.  
  74.   inc( count );
  75. end;
  76.  
  77. procedure TVehicleDatabase.WriteInfo( Index : Integer );
  78. begin
  79.   writeln( 'Vehicle[' + IntToStr( Index ) + '].CarType: ', ord( list[index].CarType ) );
  80.  
  81.   case list[index].carType of
  82.     car : With TCarParameters( list[index].Parameters^ ) do
  83.       begin
  84.         Writeln( 'Vehicle[' + IntToStr( Index ) + '].crew:  ', crew );
  85.       end;
  86.  
  87.     truck : With TTruckParameters( list[index].Parameters^ ) do
  88.       begin
  89.         writeln( 'Vehicle[' + IntToStr( Index ) + '].cargo:  ', cargo );
  90.         writeln( 'Vehicle[' + IntToStr( Index ) + '].trailer: ', trailer );
  91.       end;
  92.   end;
  93.  
  94.   writeln( '--------------------------' );
  95.   writeln;
  96. end;
  97.  
  98. procedure TVehicleDatabase.Free;
  99. var
  100.   i  : Integer;
  101. begin
  102.   for i := 0 to count -1 do
  103.     freemem( list[i].parameters );
  104. end;
  105.  
  106. var
  107.   car_params   : TCarParameters;
  108.   truck_params : TTruckParameters;
  109.   i            : Integer;
  110.  
  111. begin
  112.   DB.Init;
  113.  
  114.   car_params.crew := 1;
  115.   DB.AddVehicle( car, @car_params );
  116.  
  117.   car_params.crew := 4;
  118.   DB.AddVehicle( car, @car_params );
  119.  
  120.   truck_params.cargo := 2000;
  121.   truck_params.trailer := true;
  122.   DB.AddVehicle( truck, @truck_params );
  123.  
  124.   truck_params.cargo := 0;
  125.   truck_params.trailer := false;
  126.   DB.AddVehicle( truck, @truck_params );
  127.  
  128.   for i := 0 to DB.count -1 do
  129.     DB.WriteInfo(i);
  130.  
  131.   DB.Free;
  132.  
  133.   readkey;
  134. end.

LemonParty

  • New Member
  • *
  • Posts: 28
Re: Record with different variables - better workaround?
« Reply #1 on: June 28, 2019, 04:31:28 pm »
Put TVehicleType variable into TCarParameters and TTruckParameters (and into all other variations) as a first field, than you need to store only raw pointers inside of a hub structure.
After you can check what pointer actually is by checking the first field (use typecast, Luke).

Use New instead of GetMem.

Use Move to make an identical copy of a passing structure. I mean this code:
Code: Pascal  [Select]
  1.  pT^.cargo := TTruckParameters( _parameters^ ).cargo;
  2.  pT^.trailer := TTruckParameters( _parameters^ ).trailer;
« Last Edit: June 28, 2019, 04:52:08 pm by LemonParty »

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Record with different variables - better workaround?
« Reply #2 on: June 28, 2019, 04:57:53 pm »
Just to make sure, are you familiar with the variant part of records?

julkas

  • Sr. Member
  • ****
  • Posts: 416
  • KISS principle / Lazarus 2.0.0 / FPC 3.0.4
Re: Record with different variables - better workaround?
« Reply #3 on: June 28, 2019, 05:55:52 pm »
@Paul_ one question. Why not OOP? Why not classes?
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;

Paul_

  • Full Member
  • ***
  • Posts: 130
Re: Record with different variables - better workaround?
« Reply #4 on: June 28, 2019, 07:49:42 pm »
@LemonParty: Thanks, I will check it.

@engkin: Problem is that variant takes full size of case segment in memory, it has more specific use then.

@julkas: I'm not good in OOP, with pointers is fun and benefit is in way better performance.   

« Last Edit: June 28, 2019, 08:14:25 pm by Paul_ »

Thaddy

  • Hero Member
  • *****
  • Posts: 9191
Re: Record with different variables - better workaround?
« Reply #5 on: June 28, 2019, 08:16:21 pm »
benefit is in way better performance.
That's simply not true.
also related to equus asinus.