Recent

Author Topic: TWriter.WriteSingle() writes invalid value into *.lfm file  (Read 8206 times)

Groffy

  • Full Member
  • ***
  • Posts: 205
TWriter.WriteSingle() writes invalid value into *.lfm file
« on: July 14, 2016, 03:22:33 pm »
Hello,

just testing a 3rd party component package with Lazarus trunk / fpc 3.0 and after placing a component onto a form, it writes a property value as Single into the *.lfm file by ending the line with a "s" char. Is that the way to mark the value as data type single?

When compiling the application an exception EReadError : Invalid value for property is thrown. With Lazarus 1.6 its working without any problems. Any changes in the TWriter class?


With best regards
Linux Mint / Windows 10 / Lazarus 3.6.0 / trunk

korba812

  • Sr. Member
  • ****
  • Posts: 486
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #1 on: July 14, 2016, 04:06:22 pm »
Hello.
There are a few changes to the file lresources.pp:
http://bugs.freepascal.org/view.php?id=28040

But should be backward compatible. And is compatible with Delphi.

Can you provide a sample?

Groffy

  • Full Member
  • ***
  • Posts: 205
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #2 on: July 14, 2016, 08:33:43 pm »
I will try, but what might be the reason that the TWriter.WriteSingle() writes a "65s" into the *.lfm file?
Linux Mint / Windows 10 / Lazarus 3.6.0 / trunk

korba812

  • Sr. Member
  • ****
  • Posts: 486
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #3 on: July 15, 2016, 12:39:40 am »
Your code is correct and You did not have to provide an example. The problem lies in the methods TReader.ReadPropValue and TWriter.WriteProperty and new Lazarus functionality, that allows you to edit and save variant properties.(http://bugs.freepascal.org/view.php?id=30378)
Now some float values ar stored in LFM with letter at and.
Single values are saved with the 's' at end, currency with 'c' and date with 'd'.
Additionally, currency is stored as an integer (currency value * 10000).

Groffy

  • Full Member
  • ***
  • Posts: 205
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #4 on: July 15, 2016, 08:16:30 am »
Single values are saved with the 's' at end

Ok, so the problem seems to be to read back the correct values with the TReader class
Linux Mint / Windows 10 / Lazarus 3.6.0 / trunk

Thaddy

  • Hero Member
  • *****
  • Posts: 19388
  • Glad to be alive.
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #5 on: July 15, 2016, 08:23:57 am »
Now some float values ar stored in LFM with letter at and.
Single values are saved with the 's' at end, currency with 'c' and date with 'd'.
Additionally, currency is stored as an integer (currency value * 10000).
I have to check, but, really? That is a blatant design mistake. Those kind of info should be stored at negative offsets so the length and content can be considered opaque.
It also leads to these kind of problems and questions. This is meta-data. Meta-data describes a.o. what real data to expect. You do that beforehand.

That's a bug....

[edit some more]
I checked and indeed the info is stored at content end. That makes e.g. parsing difficult because the location of the payload description is not known beforehand and thus extremely inefficient.
That - see above - is not correct. Plz revert and do as I described/ suggest.
« Last Edit: July 15, 2016, 08:42:03 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

korba812

  • Sr. Member
  • ****
  • Posts: 486
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #6 on: July 15, 2016, 12:34:30 pm »
You're right. It seems that Delphi adds letter at the end only in variant type properties. I'll try fix it.

Thaddy

  • Hero Member
  • *****
  • Posts: 19388
  • Glad to be alive.
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #7 on: July 15, 2016, 01:54:00 pm »
only in variant type properties.
That is equally evil: Even variants (maybe even specifically variants) should not be stored like that. Variants rely on meta-data complexity, more so than other types. ;)

« Last Edit: July 15, 2016, 01:55:48 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

korba812

  • Sr. Member
  • ****
  • Posts: 486
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #8 on: July 15, 2016, 03:04:36 pm »
But in such a manner Delphi stores variant properties (attached example).
This is delphi dfm:
Code: Pascal  [Select][+][-]
  1. object Form1: TForm1
  2.   Left = 0
  3.   Top = 0
  4.   Caption = 'Form1'
  5.   ClientHeight = 249
  6.   ClientWidth = 418
  7.   Color = clBtnFace
  8.   Font.Charset = DEFAULT_CHARSET
  9.   Font.Color = clWindowText
  10.   Font.Height = -11
  11.   Font.Name = 'Tahoma'
  12.   Font.Style = []
  13.   OldCreateOrder = False
  14.   PixelsPerInch = 96
  15.   TextHeight = 13
  16.   object TestFloatVal1: TTestFloatVal
  17.     SingleVal = 123.123001098632800000
  18.     DoubleVal = 123.123000000000000000
  19.     CurrencyVal = 123.123000000000000000
  20.     DateTimeVal = 42370.523171296300000000
  21.     VarCurrency = 1231230c
  22.     VarDate = 42370.5231712963d
  23.     VarSingle = 123.123001098633s
  24.     VarDouble = 123.000000000000000000
  25.     Left = 40
  26.     Top = 32
  27.   end
  28. end
  29.  
Now I can't reproduce this problem. Seems it works fine (letter is added only to variant properties).
Can you test it?

Thaddy

  • Hero Member
  • *****
  • Posts: 19388
  • Glad to be alive.
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #9 on: July 15, 2016, 03:15:30 pm »
Delphi engineers can also make basic mistakes.
This is a basic mistake.
I wonder how that ever got through their quality control.
« Last Edit: July 15, 2016, 03:17:17 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

korba812

  • Sr. Member
  • ****
  • Posts: 486
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #10 on: July 15, 2016, 03:34:50 pm »
I do not think it was a mistake. If you look at TUTF8Parser.HandleNumber (lresources.pp), You see that even parser is prepared for that for some time.

Groffy

  • Full Member
  • ***
  • Posts: 205
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #11 on: July 16, 2016, 08:37:10 am »
However it will be implemented, at least the TReader should be able to read the values which TWriter wrote without throwing an exception.

@Thaddy : What is your idea about storing data type Variant, how to store the data type information?
Linux Mint / Windows 10 / Lazarus 3.6.0 / trunk

Thaddy

  • Hero Member
  • *****
  • Posts: 19388
  • Glad to be alive.
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #12 on: July 16, 2016, 10:26:54 am »
You store meta-data that describes what to expect before you store actual data.
The reason for that is that from the description in the meta-data you can choose the most efficient way to process the actual data.
So store a description first, then store the payload.
If you store meta-data at the end of the actual data you can not apply such a pattern.
You will have to read out all data and after that decide how to compute. That is not a very smart way to compute ;)
That is a pretty generic design pattern or even design principle:
Store meta-data before the actual data itself.
objects are fine constructs. You can even initialize them with constructors.

Thaddy

  • Hero Member
  • *****
  • Posts: 19388
  • Glad to be alive.
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #13 on: July 16, 2016, 11:22:17 am »
I do not think it was a mistake. If you look at TUTF8Parser.HandleNumber (lresources.pp), You see that even parser is prepared for that for some time.
I beg to differ because of the explanation I gave above.
That something is already implemented in a certain way does not give any indication if it is implemented in the right way. Which it isn't...

I am merely explaining theory. That is also language independent.

E.g. I want to know if I am dealing with a telephone number (which I can't do much math with and can sub-sequentially be ignored) or a read out from some sensor....
Such a decision is based on meta-data info. See the point?
« Last Edit: July 16, 2016, 11:32:13 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

korba812

  • Sr. Member
  • ****
  • Posts: 486
Re: TWriter.WriteSingle() writes invalid value into *.lfm file
« Reply #14 on: July 16, 2016, 02:36:06 pm »
I understand that. But this applies to binary data without a defined format (as in the case of streaming binary objects for example via Treader / TWriter) when you should first read the type of data and then the data. LFM / DFM has a structure - one value per line, so if you want to read the value correctly, you need to process the entire line. Another thing is that the values are saved in decimal, so still you must first read the whole line to correctly convert to binary format.

 

TinyPortal © 2005-2018