Recent

Author Topic: ToStr - Convert any value to String using RTTI  (Read 3339 times)

correa.elias

  • New member
  • *
  • Posts: 12
ToStr - Convert any value to String using RTTI
« on: October 11, 2018, 04:39:16 pm »
Automatically converts any value to a string representation, including records and arrays, in the same spirit of 'print' functions found in scripting languages. Its usefull for logging and debugging.

https://github.com/correaelias/TypeUtils
« Last Edit: October 11, 2018, 05:41:53 pm by correa.elias »

avra

  • Hero Member
  • *****
  • Posts: 1374
    • Additional info
Re: ToStr - Convert any value to String using RTTI
« Reply #1 on: October 11, 2018, 07:14:22 pm »
Thank you, very useful !    :)
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

Trenatos

  • Sr. Member
  • ****
  • Posts: 454
  • Software developer - Open source contributor
    • MarcusFernstrom.com
Re: ToStr - Convert any value to String using RTTI
« Reply #2 on: October 11, 2018, 07:25:02 pm »
I haven't tried it out, but if it works well I'd love to see it included with FPC core.

Debuggers aren't always useable (I'm looking at you, OSX) and the ability to just dump some data to a terminal/textfield is often all that's needed.

correa.elias

  • New member
  • *
  • Posts: 12
Re: ToStr - Convert any value to String using RTTI
« Reply #3 on: October 11, 2018, 07:35:31 pm »
Thanks! Im planning better examples to demonstrate the power of this function.

Code: Pascal  [Select]
  1. program Test;
  2.  
  3. uses TypeUtils, SysUtils;
  4.  
  5. type
  6.   TEmployee = record
  7.     FName: ShortString;
  8.     FId: LongInt;
  9.     FSalary: Currency;
  10.   end;
  11.  
  12. var
  13.   Employees: array of TEmployee;
  14.   I: LongInt;
  15. begin
  16.   SetLength(Employees, 10);
  17.  
  18.   for I := 0 to High(Employees) do
  19.   begin
  20.     with Employees[I] do
  21.     begin
  22.       FName := 'John Doe ' + I.ToString;
  23.       FId := I;
  24.       FSalary := 2000.25 * I;
  25.     end;
  26.   end;
  27.  
  28.   WriteLn(ToStr(Employees, TypeInfo(Employees)));
  29. end.
  30.  

outputs:
[('John Doe 0', 0, 0), ('John Doe 1', 1, 2000.25), ('John Doe 2', 2, 4000.5), ('John Doe 3', 3, 6000.75), ('John Doe 4', 4, 8001), ('John Doe 5', 5, 10001.25), ('John Doe 6', 6, 12001.5), ('John Doe 7', 7, 14001.75), ('John Doe 8', 8, 16002), ('John Doe 9', 9, 18002.25)]

zeljko

  • Hero Member
  • *****
  • Posts: 991
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: ToStr - Convert any value to String using RTTI
« Reply #4 on: October 11, 2018, 09:53:16 pm »
Nice job :)

Thaddy

  • Hero Member
  • *****
  • Posts: 7178
Re: ToStr - Convert any value to String using RTTI
« Reply #5 on: October 12, 2018, 08:30:20 am »
@correa.elias

I have reviewed the code and it looks very nice.
I have a couple of remarks, though:

1. ManagedFldCount is deprecated (at least in 3.2.0 and trunk).
    You can replace it with TotalFieldCount. (The compiler actually gives two suggestions. I chose this one)
2. I prefer {$mode Delphi}{$coperators on} over mode objfpc (see below code why!)
3. You can get rid of the typeinfo parameter and introduce type safety like so:
Code: Pascal  [Select]
  1. {$mode delphi}{$coperators on}
  2.  
  3. function ToStr(var AX; ATypeInfo: PTypeInfo): AnsiString;overload;
  4. function Tostr<T>(var Value:T):AnsiString;overload;  // <----
  5.  
  6. implementation
  7.  
  8. function Tostr<T>(var Value:T):AnsiString;overload;
  9. begin
  10.   Result :=Tostr(value,typeinfo(t));
  11. end;

My initial tests show no regressions with these minor changes. 

(objfpc mode generics look silly and won't allow this, delphi mode does allow it)
(To me objfpc mode for generics are deprecated)



« Last Edit: October 12, 2018, 09:04:50 am by Thaddy »
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

andresayang

  • Jr. Member
  • **
  • Posts: 56
Re: ToStr - Convert any value to String using RTTI
« Reply #6 on: October 12, 2018, 09:48:34 am »
Thanks
Linux, Debian 9
Lazarus: always latest release

avra

  • Hero Member
  • *****
  • Posts: 1374
    • Additional info
Re: ToStr - Convert any value to String using RTTI
« Reply #7 on: October 12, 2018, 10:19:06 am »
I haven't tried it out, but if it works well I'd love to see it included with FPC core.
+1  :)

3. You can get rid of the typeinfo parameter and introduce type safety
Very nice, thanks! I would really appreciate this change.   8)
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

wp

  • Hero Member
  • *****
  • Posts: 5118
Re: ToStr - Convert any value to String using RTTI
« Reply #8 on: October 12, 2018, 11:20:32 am »
I haven't tried it out, but if it works well I'd love to see it included with FPC core.
I don't want to disencourage you, but in my eyes, it is not flexible enough for inclusion in fcl: What if I want floats in scientific notation, integers in hex, a different field separator?
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Thaddy

  • Hero Member
  • *****
  • Posts: 7178
Re: ToStr - Convert any value to String using RTTI
« Reply #9 on: October 12, 2018, 11:59:23 am »
I don't want to disencourage you, but in my eyes, it is not flexible enough for inclusion in fcl: What if I want floats in scientific notation, integers in hex, a different field separator?

His stated purpose (in his other thread) was something similar to what Python offers: a one stop shop to print any content in a readable way.
I encouraged him to write it  :P O:-) Which he did!
That means inherently taking over some limitations.
Within that context he did a pretty good job! Within that context it is also valuable, not to the FCL but to the rtl: in sysutils.
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 6611
Re: ToStr - Convert any value to String using RTTI
« Reply #10 on: October 12, 2018, 12:05:58 pm »
I haven't tried it out, but if it works well I'd love to see it included with FPC core.
I don't want to disencourage you, but in my eyes, it is not flexible enough for inclusion in fcl: What if I want floats in scientific notation, integers in hex, a different field separator?

That requires custom attributes.  Then you can annotate that you want a color to be printed in hex etc, and the dump routine can query it.

Having both a fancy and less fancy is nice though, the fancier, the slower probably, and sometimes you just want to dump for debugging/logging purposes. This is fairly universal.

If you use this in generation of a wire protocol or file format, you want more control, hence the fancy version.

avra

  • Hero Member
  • *****
  • Posts: 1374
    • Additional info
Re: ToStr - Convert any value to String using RTTI
« Reply #11 on: October 12, 2018, 12:12:38 pm »
I haven't tried it out, but if it works well I'd love to see it included with FPC core.
I don't want to disencourage you, but in my eyes, it is not flexible enough for inclusion in fcl: What if I want floats in scientific notation, integers in hex, a different field separator?
One of the ways to enable customization for users is like we already have with DefaultFormatSettings record which is of TFormatSettings type. Anyone wanting customization could populate DefaultToStrSettings record with his own likings and everyone is happy. We could even allow optional parameter for settings record parameter. For scientific notation of floats, I think that ToStr should already use DefaultFormatSettings from FPC.

I would still prefer Str() function name instead of ToStr() - and yes, I am aware there is already a Str() procedure.
« Last Edit: October 12, 2018, 12:16:57 pm by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

Thaddy

  • Hero Member
  • *****
  • Posts: 7178
Re: ToStr - Convert any value to String using RTTI
« Reply #12 on: October 12, 2018, 12:20:06 pm »
The function is actually similar to one of the many ToJson implementations. That has also restrictions.
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

Alextp

  • Hero Member
  • *****
  • Posts: 714
    • UVviewsoft
Re: ToStr - Convert any value to String using RTTI
« Reply #13 on: October 12, 2018, 12:44:38 pm »

mr-highball

  • New member
  • *
  • Posts: 17
Re: ToStr - Convert any value to String using RTTI
« Reply #14 on: October 12, 2018, 05:29:28 pm »
@correa.elias

I have reviewed the code and it looks very nice.
I have a couple of remarks, though:

1. ManagedFldCount is deprecated (at least in 3.2.0 and trunk).
    You can replace it with TotalFieldCount. (The compiler actually gives two suggestions. I chose this one)
2. I prefer {$mode Delphi}{$coperators on} over mode objfpc (see below code why!)
3. You can get rid of the typeinfo parameter and introduce type safety like so:
Code: Pascal  [Select]
  1. {$mode delphi}{$coperators on}
  2.  
  3. function ToStr(var AX; ATypeInfo: PTypeInfo): AnsiString;overload;
  4. function Tostr<T>(var Value:T):AnsiString;overload;  // <----
  5.  
  6. implementation
  7.  
  8. function Tostr<T>(var Value:T):AnsiString;overload;
  9. begin
  10.   Result :=Tostr(value,typeinfo(t));
  11. end;

My initial tests show no regressions with these minor changes. 

(objfpc mode generics look silly and won't allow this, delphi mode does allow it)
(To me objfpc mode for generics are deprecated)

thanks this is nice, also I would second the templated version
-Highball