Re: [fpc-devel] restbase.pp LoadFromJSON calling StopRecordPropertyChanges;

2023-01-14 Thread Wayne Sherman via fpc-devel
I see a couple of problems TBaseObject.SaveToJSON

1) TBaseObject.SaveToJSON cannot distinguish properties that are part
of the REST protocol from properties that are not part of it.  It only
knows that properties which have been modified are part of the rest
protocol, but properties which have not been modified might be part of
the REST protocol or might not be.  For example, a client receives a
JSON object from a server (via LoadFromJSON) and wants to persist the
complete JSON object to disk, database, or send it to another server.
But, at present, there is no way to save all the properties that are
part of the REST protocol without getting contaminated with non-REST
properties.

2) Lack of control.  With TBaseObject.SaveToJSON it would be nice to
control what is saved (Save all REST properties, or Save modified REST
properties).
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] restbase.pp LoadFromJSON calling StopRecordPropertyChanges;

2023-01-14 Thread Wayne Sherman via fpc-devel
Michael wrote:
> >> Because there may be other published properties that are not part of the
> >> REST protocol. You may for instance decide to add published properties to a
> >> base class that describe where to save the object in a local database.

Wayne wrote:
> > Ok, that clears up that.  If I understand correctly, the behavior
> > should be as follows:
> >
> > (restbase.pp)
> > In TBaseObject descendants, SaveToJSON only saves object properties
> > defined directly in the final descendant class and none of the
> > properties of parent classes.  This is implemented by only marking
> > properties as modified that are defined directly in the final
> > descendant class and skipping properties of all parent classes (which
> > always appear to be unmodified, and thus not saved).  This prevents
> > properties which are not part of the REST protocol from contaminating
> > the generated JSON.  It follows that REST protocol properties should
> > always be defined in the final TBaseObject descendant class (and not
> > in any base or intermediate classes).

Michael wrote:
> While in practice most REST classes will be the final classes,
> it should be possible to support inheritance in rest classes,
> that is why the 'ParentPropertyCount' exists and is taken into account.

My summary above is incorrect.  How about this?:

In TBaseObject descendants, SaveToJSON only saves object properties
which have had their properties marked as modified using
MarkPropertyChanged (modified flags are stored internally using
TBits).  Properties which have not been marked as modified will not be
saved to JSON.  This prevents properties which are not part of the
REST protocol from contaminating the generated JSON.

Auto generated code that defines TBaseObject descendant classes
declares properties with index specifiers and setter methods that call
MarkPropertyChanged.  When a property is changed in these auto
generated classes, that property will end up in the output of
SaveToJSON.  Properties which are a valid part of the REST protocol,
but which have not been changed are not included in the generated
JSON.

Properties can be defined in a TBaseObject final descendant class or
parent classes and be included in the JSON output (as long as
MarkPropertyChanged has been called with the corresponding index for
that property).
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] restbase.pp LoadFromJSON calling StopRecordPropertyChanges;

2023-01-14 Thread Michael Van Canneyt via fpc-devel




On Sat, 14 Jan 2023, Wayne Sherman wrote:


On Sat, Jan 14, 2023 at 12:36 PM Michael Van Canneyt wrote:

On Sat, 14 Jan 2023, Wayne Sherman wrote:

On Sat, Jan 14, 2023 at 10:34 AM Michael Van Canneyt wrote:

On Sat, 14 Jan 2023, Wayne Sherman wrote:

2) Doesn't each object already have the parent properties included in
its own properties by inheritance?


Why this question ?
An object does not know the property count of the parent.


True, but why does it need to know the property count of the parent?

 TBaseClass = class
 private
   FField1: integer;
 protected
   FPropModifiedFlags: TBits;
 published
   property Field1: integer read FField1 write FField1;
 end;

GetTypeData(TBaseClass.ClassInfo)^.PropCount = 1

 TDescendant = class(TBaseClass)
 private
   FField2: integer;
 published
   property Field2: integer read FField2 write FField2;
 end;

GetTypeData(TDescendant.ClassInfo)^.PropCount = 2

TDescendant has two properties (one inherited and one declared
directly) and let's say it can record if any of the properties have
been modified.  So why does it have to know about the number of
properties it inherited vs the properties it declares directly?


Because there may be other published properties that are not part of the
REST protocol. You may for instance decide to add published properties to a
base class that describe where to save the object in a local database.


Ok, that clears up that.  If I understand correctly, the behavior
should be as follows:

(restbase.pp)
In TBaseObject descendants, SaveToJSON only saves object properties
defined directly in the final descendant class and none of the
properties of parent classes.  This is implemented by only marking
properties as modified that are defined directly in the final
descendant class and skipping properties of all parent classes (which
always appear to be unmodified, and thus not saved).  This prevents
properties which are not part of the REST protocol from contaminating
the generated JSON.  It follows that REST protocol properties should
always be defined in the final TBaseObject descendant class (and not
in any base or intermediate classes).



While in practice most REST classes will be the final classes, 
it should be possible to support inheritance in rest classes, 
that is why the 'ParentPropertyCount' exists and is taken into account.


Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] restbase.pp LoadFromJSON calling StopRecordPropertyChanges;

2023-01-14 Thread Wayne Sherman via fpc-devel
On Sat, Jan 14, 2023 at 12:36 PM Michael Van Canneyt wrote:
> On Sat, 14 Jan 2023, Wayne Sherman wrote:
> > On Sat, Jan 14, 2023 at 10:34 AM Michael Van Canneyt wrote:
> >> On Sat, 14 Jan 2023, Wayne Sherman wrote:
> >>> 2) Doesn't each object already have the parent properties included in
> >>> its own properties by inheritance?
> >>
> >> Why this question ?
> >> An object does not know the property count of the parent.
> >
> > True, but why does it need to know the property count of the parent?
> >
> >  TBaseClass = class
> >  private
> >FField1: integer;
> >  protected
> >FPropModifiedFlags: TBits;
> >  published
> >property Field1: integer read FField1 write FField1;
> >  end;
> >
> > GetTypeData(TBaseClass.ClassInfo)^.PropCount = 1
> >
> >  TDescendant = class(TBaseClass)
> >  private
> >FField2: integer;
> >  published
> >property Field2: integer read FField2 write FField2;
> >  end;
> >
> > GetTypeData(TDescendant.ClassInfo)^.PropCount = 2
> >
> > TDescendant has two properties (one inherited and one declared
> > directly) and let's say it can record if any of the properties have
> > been modified.  So why does it have to know about the number of
> > properties it inherited vs the properties it declares directly?
>
> Because there may be other published properties that are not part of the
> REST protocol. You may for instance decide to add published properties to a
> base class that describe where to save the object in a local database.

Ok, that clears up that.  If I understand correctly, the behavior
should be as follows:

(restbase.pp)
In TBaseObject descendants, SaveToJSON only saves object properties
defined directly in the final descendant class and none of the
properties of parent classes.  This is implemented by only marking
properties as modified that are defined directly in the final
descendant class and skipping properties of all parent classes (which
always appear to be unmodified, and thus not saved).  This prevents
properties which are not part of the REST protocol from contaminating
the generated JSON.  It follows that REST protocol properties should
always be defined in the final TBaseObject descendant class (and not
in any base or intermediate classes).
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] restbase.pp LoadFromJSON calling StopRecordPropertyChanges;

2023-01-14 Thread Wayne Sherman via fpc-devel
On Sat, Jan 14, 2023 at 10:34 AM Michael Van Canneyt wrote:
> On Sat, 14 Jan 2023, Wayne Sherman wrote:
> > 3) Why does MarkPropertyChanged offset the index and
> > IsPropertyModified does not take the offset into account?
>
> They should be the same. I don't remember why I created the two methods
> differently.

For property index specifiers, it seems that NameIndex might be the
wrong index used in IsPropertyModified:

function TBaseObject.IsPropertyModified(Info: PPropInfo): Boolean;
begin
  Result:=Not Assigned(FBits) or FBits.Bits[Info^.NameIndex]
end;

and possibly the rtl docs are incorrect(?):
   https://www.freepascal.org/docs-html/rtl/typinfo/tpropinfo.html
   Index - Index for array properties
   NameIndex - Index for indexed properties  << IS THIS CORRECT?

In the typinfo.pp unit, a comment indicates that NameIndex has to do
with property names (i.e. not the index specifier)
https://gitlab.com/freepascal.org/fpc/source/-/blob/main/rtl/objpas/typinfo.pp#L1689
// Don't overwrite properties with the same name
if PropList^[TP^.NameIndex]=nil then
  PropList^[TP^.NameIndex]:=TP;
// Point to TP next propinfo record.
// Located at Name[Length(Name)+1] !
TP:=aligntoptr(PPropInfo(pointer(@TP^.Name)+PByte(@TP^.Name)^+1));
Dec(Count);
  end;

NameIndex in Delphi typeinfo also has to do with Names of properties
and Index has the information on indexed properties:
   https://docwiki.embarcadero.com/Libraries/Sydney/en/System.TypInfo.TPropInfo
   Index - The index of the property. It is used as a parameter to the
GetProc and SetProc methods on indexed properties.
   NameIndex - The offset into the Name field where the property's name starts.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] restbase.pp LoadFromJSON calling StopRecordPropertyChanges;

2023-01-14 Thread Michael Van Canneyt via fpc-devel




On Sat, 14 Jan 2023, Wayne Sherman wrote:


On Sat, Jan 14, 2023 at 10:34 AM Michael Van Canneyt wrote:

On Sat, 14 Jan 2023, Wayne Sherman wrote:

2) Doesn't each object already have the parent properties included in
its own properties by inheritance?


Why this question ?
An object does not know the property count of the parent.


True, but why does it need to know the property count of the parent?

 TBaseClass = class
 private
   FField1: integer;
 protected
   FPropModifiedFlags: TBits;
 published
   property Field1: integer read FField1 write FField1;
 end;

GetTypeData(TBaseClass.ClassInfo)^.PropCount = 1

 TDescendant = class(TBaseClass)
 private
   FField2: integer;
 published
   property Field2: integer read FField2 write FField2;
 end;

GetTypeData(TDescendant.ClassInfo)^.PropCount = 2

TDescendant has two properties (one inherited and one declared
directly) and let's say it can record if any of the properties have
been modified.  So why does it have to know about the number of
properties it inherited vs the properties it declares directly?


Because there may be other published properties that are not part of the
REST protocol. You may for instance decide to add published properties to a
base class that describe where to save the object in a local database.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] restbase.pp LoadFromJSON calling StopRecordPropertyChanges;

2023-01-14 Thread Wayne Sherman via fpc-devel
On Sat, Jan 14, 2023 at 10:34 AM Michael Van Canneyt wrote:
> On Sat, 14 Jan 2023, Wayne Sherman wrote:
> > 2) Doesn't each object already have the parent properties included in
> > its own properties by inheritance?
>
> Why this question ?
> An object does not know the property count of the parent.

True, but why does it need to know the property count of the parent?

  TBaseClass = class
  private
FField1: integer;
  protected
FPropModifiedFlags: TBits;
  published
property Field1: integer read FField1 write FField1;
  end;

GetTypeData(TBaseClass.ClassInfo)^.PropCount = 1

  TDescendant = class(TBaseClass)
  private
FField2: integer;
  published
property Field2: integer read FField2 write FField2;
  end;

GetTypeData(TDescendant.ClassInfo)^.PropCount = 2

TDescendant has two properties (one inherited and one declared
directly) and let's say it can record if any of the properties have
been modified.  So why does it have to know about the number of
properties it inherited vs the properties it declares directly?
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] restbase.pp LoadFromJSON calling StopRecordPropertyChanges;

2023-01-14 Thread Michael Van Canneyt via fpc-devel




On Sat, 14 Jan 2023, Wayne Sherman wrote:


On Fri, Jan 13, 2023 at 11:48 PM Michael Van Canneyt wrote:

Markpropertychanged is called in the setter of the properties generated by
the code generator: Check all generated units.


Thanks for your explanations, it is getting more clear how modified
property tracking is being used.

More clarification please.  MarkPropertyChanged offsets the property
changed index (to TBits) by the ClassParent total property count, but
IsPropertyModified does not take this offset into account.  Consider
this example:

TBaseObject --> TGoogleBaseObject --> TSchema --> TMySchema
TBaseObjectClass = Class of TBaseObject;

If the object is TMySchema, in GetParentPropCount the TBits index gets
offset by (see reference code below):
 TBaseObjectClass(TSchema).GetTotalPropCount;
If the object is TSchema, the TBits index gets offset by:
 TBaseObjectClass(TGoogleBaseObject).GetTotalPropCount;

Questions:
1) Since the ClassParent is always cast as TBaseObjectClass isn't this
the same as just TBaseObjectClass(Self.ClassType)?


No. The method is virtual, so the actual descendant's method is called.



2) Doesn't each object already have the parent properties included in
its own properties by inheritance?


Why this question ? 
An object does not know the property count of the parent.





3) Why does MarkPropertyChanged offset the index and
IsPropertyModified does not take the offset into account?


They should be the same. I don't remember why I created the two methods
differently.

Michael.



Reference for above questions:

class function TBaseObject.GetParentPropCount: Integer;
begin
 if (ClassParent=TBaseObject) or (ClassParent=Nil) then
   Result:=0
 else
   Result:=TBaseObjectClass(ClassParent).GetTotalPropCount;
end;

procedure TBaseObject.MarkPropertyChanged(AIndex: Integer);
begin
 If Assigned(FBits) then
   FBits.SetOn(GetParentPropCount+(AIndex shr IndexShift));
end;

function TBaseObject.IsPropertyModified(Info: PPropInfo): Boolean;
begin
 Result:=Not Assigned(FBits) or FBits.Bits[Info^.NameIndex]
end;




___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] restbase.pp LoadFromJSON calling StopRecordPropertyChanges;

2023-01-14 Thread Wayne Sherman via fpc-devel
On Fri, Jan 13, 2023 at 11:48 PM Michael Van Canneyt wrote:
> Markpropertychanged is called in the setter of the properties generated by
> the code generator: Check all generated units.

Thanks for your explanations, it is getting more clear how modified
property tracking is being used.

More clarification please.  MarkPropertyChanged offsets the property
changed index (to TBits) by the ClassParent total property count, but
IsPropertyModified does not take this offset into account.  Consider
this example:

TBaseObject --> TGoogleBaseObject --> TSchema --> TMySchema
TBaseObjectClass = Class of TBaseObject;

If the object is TMySchema, in GetParentPropCount the TBits index gets
offset by (see reference code below):
  TBaseObjectClass(TSchema).GetTotalPropCount;
If the object is TSchema, the TBits index gets offset by:
  TBaseObjectClass(TGoogleBaseObject).GetTotalPropCount;

Questions:
1) Since the ClassParent is always cast as TBaseObjectClass isn't this
the same as just TBaseObjectClass(Self.ClassType)?

2) Doesn't each object already have the parent properties included in
its own properties by inheritance?

3) Why does MarkPropertyChanged offset the index and
IsPropertyModified does not take the offset into account?

Reference for above questions:

class function TBaseObject.GetParentPropCount: Integer;
begin
  if (ClassParent=TBaseObject) or (ClassParent=Nil) then
Result:=0
  else
Result:=TBaseObjectClass(ClassParent).GetTotalPropCount;
end;

procedure TBaseObject.MarkPropertyChanged(AIndex: Integer);
begin
  If Assigned(FBits) then
FBits.SetOn(GetParentPropCount+(AIndex shr IndexShift));
end;

function TBaseObject.IsPropertyModified(Info: PPropInfo): Boolean;
begin
  Result:=Not Assigned(FBits) or FBits.Bits[Info^.NameIndex]
end;


___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Why: "Can't take the address of constant expressions" here?

2023-01-14 Thread wkitty42--- via fpc-devel

On 1/13/23 5:35 AM, Bart via fpc-devel wrote:

On Fri, Jan 13, 2023 at 11:13 AM wkitty42--- via fpc-devel
 wrote:





First of all, adding a 'end;" for the "with" compiles under Linux.
That's because widestring=unicodestring on Linux.


i'm a little surprised there is no "mismatched begin/end" error with the caret
pointing to the 2nd begin...

--


That's a copy/paste error.by me.
The original code had about 10 more function calls and then a closing
end for the "with WideStringManager do begin "



oh! that would explain it :lol:


--
 NOTE: No off-list assistance is given without prior approval.
   *Please keep mailing list traffic on the list where it belongs!*
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel