Recent

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

Paul_

  • Full Member
  • ***
  • Posts: 143
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

  • Jr. Member
  • **
  • Posts: 58
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: 3112
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

  • Guest
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?

Paul_

  • Full Member
  • ***
  • Posts: 143
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: 14197
  • Probably until I exterminate Putin.
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.
Specialize a type, not a var.

 

TinyPortal © 2005-2018