Recent

Author Topic: Little bit confusing PChar operation  (Read 2966 times)

Thaddy

  • Hero Member
  • *****
  • Posts: 16194
  • Censorship about opinions does not belong here.
Re: Little bit confusing PChar operation
« Reply #15 on: June 15, 2024, 07:23:10 am »
Classes are also pointers, as opposed to objects (which behave like records)
If I smell bad code it usually is bad code and that includes my own code.

egsuh

  • Hero Member
  • *****
  • Posts: 1493
Re: Little bit confusing PChar operation
« Reply #16 on: June 15, 2024, 07:57:27 am »
Quote
Classes are also pointers, as opposed to objects (which behave like records)

I know. The classes there may be accessed even after TaqValue has been released.

TaqValue was not designed as self-data-containing record. I'm using this as an intermediary storage --- calculated data actually. For an example, an expression like "2 * 3" will be stored in TExpression as input string. The calculated value (i.e. integer 6) is stored in TaqValue.

ASerge

  • Hero Member
  • *****
  • Posts: 2338
Re: Little bit confusing PChar operation
« Reply #17 on: June 15, 2024, 10:53:41 am »
I can mix fixed fields, methods, and variant fields in record.
Only when {$LONGSTRINGS OFF}. Error: Data types which require initialization/finalization cannot be used in variant records.

egsuh

  • Hero Member
  • *****
  • Posts: 1493
Re: Little bit confusing PChar operation
« Reply #18 on: June 15, 2024, 11:30:52 am »
Quote
Only when {$LONGSTRINGS OFF}. Error: Data types which require initialization/finalization cannot be used in variant records.

In my example, string is not defined within variant part of the record. Do I still need {$LONGSTRINGS OFF}?

What I need in the end is an expression parser and evaluator.

https://wiki.freepascal.org/How_To_Use_TFPExpressionParser

I found this page now, and there are similar approach to my idea (If I had read this in the past, I don't have to think over now).

Code: Pascal  [Select][+][-]
  1. type
  2.   TResultType = (rtBoolean, rtInteger, rtFloat, tDateTime, rtString);
  3.  
  4.   TFPExpressionResult = record
  5.     ResString   : String;
  6.     Case ResultType : TResultType of
  7.       rtBoolean  : (ResBoolean  : Boolean);
  8.       rtInteger  : (ResInteger  : Int64);
  9.       rtFloat    : (ResFloat    : TExprFloat);
  10.       rtDateTime : (ResDateTime : TDatetime);
  11.       rtString   : ();
  12.   end;
  13.  

I need one more type --- set or array. And there could be variables, whose values should be given from outside.

ASerge

  • Hero Member
  • *****
  • Posts: 2338
Re: Little bit confusing PChar operation
« Reply #19 on: June 15, 2024, 11:46:49 am »
In my example, string is not defined within variant part of the record. Do I still need {$LONGSTRINGS OFF}?
The message I replied to was:
Code: Pascal  [Select][+][-]
  1. type
  2.     RRec= record
  3.           ThingToDo: string;
  4.  
  5.           procedure SetRecValue(rtype:integer; AValue:string);
  6.  
  7.           case rectype: integer of
  8.                  1:  (Month: string);  // <- THIS!!!
  9.                  2:  (Date: integer);
  10.     end;

egsuh

  • Hero Member
  • *****
  • Posts: 1493
Re: Little bit confusing PChar operation
« Reply #20 on: June 15, 2024, 11:58:50 am »
In my example, string is not defined within variant part of the record. Do I still need {$LONGSTRINGS OFF}?
The message I replied to was:
Code: Pascal  [Select][+][-]
  1. type
  2.     RRec= record
  3.           ThingToDo: string;
  4.  
  5.           procedure SetRecValue(rtype:integer; AValue:string);
  6.  
  7.           case rectype: integer of
  8.                  1:  (Month: string);  // <- THIS!!!
  9.                  2:  (Date: integer);
  10.     end;

OMG. In real test program, it was String[10]. Sorry for the error. I ran test program on another PC and wrote it here based on memory. My point here was ThingTodo. But this was already documented.

alpine

  • Hero Member
  • *****
  • Posts: 1303
Re: Little bit confusing PChar operation
« Reply #21 on: June 16, 2024, 10:23:55 am »
@egsuh
Here is how to solve your issue from the original post. The additional property will help managing memory through it's getter/setter:
Code: Pascal  [Select][+][-]
  1. {$MODESWITCH ADVANCEDRECORDS}
  2. type
  3.   TResultType = (rtBoolean, rtInteger, rtFloat, rtDateTime, rtString);
  4.  
  5.   TExprFloat = Double;
  6.  
  7.   { TFPExpressionResult }
  8.  
  9.   TFPExpressionResult = record
  10.   private
  11.     function GetResString: AnsiString;
  12.     procedure SetResString(AValue: AnsiString);
  13.     class operator Finalize(var ASelf: TFPExpressionResult); inline;
  14.   public
  15.     property ResString: AnsiString read GetResString write SetResString;
  16.     //ResString   : String;
  17.     Case ResultType : TResultType of
  18.       rtBoolean  : (ResBoolean  : Boolean);
  19.       rtInteger  : (ResInteger  : Int64);
  20.       rtFloat    : (ResFloat    : TExprFloat);
  21.       rtDateTime : (ResDateTime : TDatetime);
  22.       rtString   : (ResString_: PChar);
  23.   end;
  24.  
  25. { TFPExpressionResult }
  26.  
  27. function TFPExpressionResult.GetResString: AnsiString;
  28. begin
  29.   Result := ResString_;
  30. end;
  31.  
  32. procedure TFPExpressionResult.SetResString(AValue: AnsiString);
  33. var
  34.   L: SizeInt;
  35. begin
  36.   if Assigned(ResString_) then
  37.   begin
  38.     FreeMem(ResString_);
  39.     ResString_ := Nil;
  40.   end;
  41.   L := Length(AValue);
  42.   if L > 0 then
  43.   begin
  44.     GetMem(ResString_, L + 1);
  45.     Move(AValue[1], ResString_^, L + 1);
  46.   end;
  47. end;
  48.  
  49. class operator TFPExpressionResult.Finalize(var ASelf: TFPExpressionResult);
  50. begin
  51.   if Assigned(ASelf.ResString_) then
  52.     FreeMem(ASelf.ResString_);
  53. end;
  54.  
  55. var
  56.   R: TFPExpressionResult;
  57.  
  58. begin
  59.   R.ResString := 'AnsiString';
  60.   WriteLn('''', R.ResString, '''');
  61.   R.ResString := 'Another AnsiString';
  62.   WriteLn('''', R.ResString, '''');
  63.   R.ResString := '';
  64.   WriteLn('''', R.ResString, '''');
  65. end.  
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

egsuh

  • Hero Member
  • *****
  • Posts: 1493
Re: Little bit confusing PChar operation
« Reply #22 on: June 17, 2024, 03:17:57 am »
@alpine

Really appreciate your comment. Actually I'm thinking of defining function like:

Code: Pascal  [Select][+][-]
  1. function TFPExpressionResult.GetResString: AnsiString;
  2. begin
  3.     case ResultType of
  4.         rtBoolean: Result := BoolToStr(ResBoolean, true);
  5.         rtInteger: Result := IntToStr(ResInteger);
  6.         // ......
  7.         rtString:  Result := ResString_;
  8.    end;
  9. end;

for external access. In most cases results are converted to string in the end (like 35 in "You answered your age is 35.", etc.).

 

TinyPortal © 2005-2018