[fpc-pascal] How to contribute a Unit

2024-02-03 Thread Amir--- via fpc-pascal

Hi,

  In www.freepascal.org, I see there is a "Contributed Units" tab. What 
are the criteria for a unit to be qualified to be placed there. How can 
one build a community account?


Best,
Amir
P.S. Here  is the unit I 
want to contribute.___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Read Field names from VMT

2024-02-01 Thread Amir--- via fpc-pascal

I see... The trick was to define TMyClass!

Thanks!


On 2/1/24 02:19, Michael Van Canneyt via fpc-pascal wrote:



On Wed, 31 Jan 2024, Amir--- via fpc-pascal wrote:



Without more info (declaration of ChildTClass, declaration of the 
constructor

of that class etc), it is not possible to comment.

We need a complete compilable code sample to provide you with more 
insight.



Please have a look at the attachment.


The constructor of TObject is not virtual, in difference with the 
destructor.


Given the definitions

  ChildObj: TObject;
  ChildTClass: TClass;

The following statement

  ChildObj := ChildTClass.Create;

will always use the TObject.Create, since it is not virtual.

In general, you cannot use TObject for this kind of thing.

For this to work, you need to create a descendent of TObject with a 
virtual

constructor (call it TMyObject) of known signature, and do

  ChildObj: TMyObject;
  ChildTClass: TMyClass; // class of TMyobject

then

  ChildObj := ChildTClass.Create;

will take the correct overridden constructor.

Your code is also incomplete in the sense that it will only work for 
classes
with a constructor without arguments. If a overloaded constructor 
exists which takes arguments (like TComponent), it will not be called 
and the class will not be instantiated correctly.

But maybe that will not be your use-case.

I attached a version of your program that works and has no memleaks.

Michael.

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


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


Re: [fpc-pascal] Read Field names from VMT

2024-01-31 Thread Amir--- via fpc-pascal


Without more info (declaration of ChildTClass, declaration of the 
constructor

of that class etc), it is not possible to comment.

We need a complete compilable code sample to provide you with more 
insight.



Please have a look at the attachment.

Best,
Amir

FieldAddress.lpr.gz
Description: application/gzip
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Read Field names from VMT

2024-01-29 Thread Amir--- via fpc-pascal

I am still struggling with this!

for i := 0 to vft^.Count - 1 do
begin
   vfe := vft^.Field[i];
   Name := vfe^.Name;

   ChildTClass := vft^.ClassTab^.ClassRef[vfe^.TypeIndex - 1]^;
   ChildObj := ChildTClass.Create;
   TObject(Obj.FieldAddress(Name)^) := ChildObj;
end;

Looks like "ChildTClass.ClassName" is correct but the constructor of the 
appropriate class is not being called.



On 1/22/24 23:05, Michael Van Canneyt via fpc-pascal wrote:



On Mon, 22 Jan 2024, Amir--- via fpc-pascal wrote:


  Params := TParams.Create;
  WriteLn(Params.Int2.IntVal);
  WriteLn(TInteger(Params.FieldAddress('Int2')).IntVal);

The third line does not work (the zipped code is attached).


It should be

WriteLn(TInteger(Params.FieldAddress('Int2')^).IntVal);

Terribly convoluted code, though...

Michael.

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


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


Re: [fpc-pascal] Read Field names from VMT

2024-01-22 Thread Amir--- via fpc-pascal



On 1/22/24 23:05, Michael Van Canneyt via fpc-pascal wrote:



On Mon, 22 Jan 2024, Amir--- via fpc-pascal wrote:


  Params := TParams.Create;
  WriteLn(Params.Int2.IntVal);
  WriteLn(TInteger(Params.FieldAddress('Int2')).IntVal);

The third line does not work (the zipped code is attached).


It should be

WriteLn(TInteger(Params.FieldAddress('Int2')^).IntVal);

+1

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


Re: [fpc-pascal] Read Field names from VMT

2024-01-22 Thread Amir--- via fpc-pascal

  Params := TParams.Create;
  WriteLn(Params.Int2.IntVal);
  WriteLn(TInteger(Params.FieldAddress('Int2')).IntVal);

The third line does not work (the zipped code is attached).

On 1/21/24 23:43, Michael Van Canneyt via fpc-pascal wrote:



On Sun, 21 Jan 2024, Amir--- via fpc-pascal wrote:


How can I set the value?
I tried something like

Test := TTest.Create

Ptr := Pointer(Test);
TSub(Ptr+8) := TSub.Create;

But it is not working?


Depending on your platform, it can be an alignment issue.

Use

 function TObject.FieldAddress(const name : shortstring) : pointer;

This function is used internally by the streaming system (see
TComponent.SetReference), so it should always work.

Michael.

You can use the PVmtFieldTable and PVmtFieldEntry types from the 
TypInfo unit:


=== code begin ===

program tfield;

{$mode objfpc}{$H+}

uses
  TypInfo;

type
  {$M+}
  TSub = class

  end;

  TTest = class
  published
    fTest: TSub;
  end;

var
  vft: PVmtFieldTable;
  vfe: PVmtFieldEntry;
  i: SizeInt;
begin
  vft := PVmtFieldTable(PVMT(TTest)^.vFieldTable);
  Writeln(vft^.Count, ' field(s) with ', vft^.ClassTab^.Count, ' 
type(s)');

  for i := 0 to vft^.Count - 1 do begin
    vfe := vft^.Field[i];
    Writeln(i, ' -> ', vfe^.Name, ' @ ', vfe^.FieldOffset, ' of type 
', vft^.ClassTab^.ClassRef[vfe^.TypeIndex - 1]^.ClassName);

  end;
end.

=== code end ===

=== output begin ===

PS C:\fpc\git> .\testoutput\tfield.exe
1 field(s) with 1 type(s)
0 -> fTest @ 8 of type TSub

=== output end ===

Side note: contrary to what I had originally written only classes, 
but not interfaces are allowed for published fields and they need to 
have $M enabled.


Regards,
Sven

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


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



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


FieldAddress.lpr.gz
Description: application/gzip
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Read Field names from VMT

2024-01-21 Thread Amir--- via fpc-pascal

How can I set the value?
I tried something like

Test := TTest.Create

Ptr := Pointer(Test);
TSub(Ptr+8) := TSub.Create;

But it is not working?
You can use the PVmtFieldTable and PVmtFieldEntry types from the 
TypInfo unit:


=== code begin ===

program tfield;

{$mode objfpc}{$H+}

uses
  TypInfo;

type
  {$M+}
  TSub = class

  end;

  TTest = class
  published
    fTest: TSub;
  end;

var
  vft: PVmtFieldTable;
  vfe: PVmtFieldEntry;
  i: SizeInt;
begin
  vft := PVmtFieldTable(PVMT(TTest)^.vFieldTable);
  Writeln(vft^.Count, ' field(s) with ', vft^.ClassTab^.Count, ' 
type(s)');

  for i := 0 to vft^.Count - 1 do begin
    vfe := vft^.Field[i];
    Writeln(i, ' -> ', vfe^.Name, ' @ ', vfe^.FieldOffset, ' of type 
', vft^.ClassTab^.ClassRef[vfe^.TypeIndex - 1]^.ClassName);

  end;
end.

=== code end ===

=== output begin ===

PS C:\fpc\git> .\testoutput\tfield.exe
1 field(s) with 1 type(s)
0 -> fTest @ 8 of type TSub

=== output end ===

Side note: contrary to what I had originally written only classes, but 
not interfaces are allowed for published fields and they need to have 
$M enabled.


Regards,
Sven

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


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


Re: [fpc-pascal] How to avoid Copy

2024-01-02 Thread Amir--- via fpc-pascal

Thanks!

On 1/2/24 22:59, Sven Barth via fpc-pascal wrote:
Amir--- via fpc-pascal  schrieb am 
Mi., 3. Jan. 2024, 07:53:


Yeap! That is actually what I posted here (Feature Request)
<https://gitlab.com/freepascal.org/fpc/source/-/issues/40578>.


My example allows you to access it right now with the existing FPC 
release.


Regards,
Sven


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


Re: [fpc-pascal] How to avoid Copy

2024-01-02 Thread Amir--- via fpc-pascal
Yeap! That is actually what I posted here (Feature Request) 
.


 You simply need to inherit from the list class so that you can make 
the function public. And with a little trick you can also use it 
inside a for-in-loop:


=== code begin ===

program tlistitr;

{$mode objfpc}{$H+}
{$modeswitch advancedrecords}

uses
  Generics.Collections;

type
  TRec = record
    a, b, c: Int64;
    constructor Create(aArg1, aArg2, aArg3: Int64);
  end;

  { this way the GetPtrEnumerator function is available; you could 
also use a class helper }

  TMyList = class(specialize TList)
  public
    function GetPtrEnumerator: specialize TEnumerator;
  end;

constructor TRec.Create(aArg1, aArg2, aArg3: Int64);
begin
  a := aArg1;
  b := aArg2;
  c := aArg3;
end;

function TMyList.GetPtrEnumerator: specialize TEnumerator;
begin
  Result := inherited GetPtrEnumerator();
end;

{ with this you can simply do "for PtrTypeVar in List.GetPtrEnumerator 
do",

  though this *might* not work in mode Delphi... }
operator Enumerator(aEnum: specialize TEnumerator): 
specialize TEnumerator;

begin
  Result := aEnum;
end;

var
  l: TMyList;
  r: TRec;
  p: TMyList.PT;
begin
  l := TMyList.Create;
  l.Add(TRec.Create(1, 2, 3));
  l.Add(TRec.Create(9, 8, 7));
  for p in l.GetPtrEnumerator do begin
    Writeln(p^.a, ' ', p^.b, ' ', p^.c);
  end;
end.

=== code end ===

Regards,
Sven

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


Re: [fpc-pascal] How to avoid Copy

2023-12-31 Thread Amir--- via fpc-pascal



On 12/31/23 02:46, Marco van de Voort via fpc-pascal wrote:


Op 31/12/2023 om 04:11 schreef Amir--- via fpc-pascal:


I compiled the code with `fpc -O3 -Sd -gv -g -gl ` and ran `valgrind` 
on it (the output is attached). It does not look like there is a big 
difference between the Check1 and Check2 but Check3 is about 20 times 
faster than the other two.
I believe the issue could be resolved if we make 
"TCustomListWithPointers.GetPtrEnumerator" a public method. Then, one 
can implement the following function:


 I also do this (an enumerator using a pointer type) in one of my 
container types. It also makes assignment in the for in possible. Note 
though that it is not necessarily needed to switch the whole 
collection to use a pointer, defining a separate iterator (e.g. 
collection.pointeriterator) that returns an iterator instantiated for 
^T.   You can then select the iterator by using for element in 
collection.iterator do.
Understand (and this is what I ended-up doing). I guess my question is 
that why we do not to have a PointerIterator in TList class.


Amir

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


Re: [fpc-pascal] How to avoid Copy

2023-12-29 Thread Amir via fpc-pascal
On Dec 29, 2023 9:50 PM, Adriaan van Os  wrote:Amir--- via fpc-pascal wrote:

> Hi all,

> 

>  I have a List of record, where the record has a WideString field.

>   I have some code like the following:

> 

> function check(constref v: TMyRecord; data: TListOfMyRecord): Boolean;

> var

>   r: TMyRecord;

> 

> begin

>   Result := False;

>   for r in data do

> if r.State = v.State then

>   Exit(True);

> end;

> 

> I call this method a lot and the CPU profiling shows a lot of cpu time 

> spent on "fpc_copy_proc" (which I assume is doing the deep copy on 

> records) from "TCustomListEnumerator.GetCurrent".

> I considered other alternatives like using enumerators but they all need 

> a to return a record (and hence copying the widestring field).

> I can think of two solutions to get rid of the wasting(!) so much time 

> on "fpc_copy_proc":

> 1) Changing the TMyRecord to TMyClass. But then I need to Create and 

> Free a "lot" of objects.

> 2) Update TListOfMyRecord to TListOfPointerToMyRecord. This requires a 

> "lot" of memory allocation/fragmentation.

> 

> Is there a better solution?



Pass the data parameter by reference.This means I need to have a ListOfMyRecord and a ListOfConstRefMyRecord, right?



Regards,



Adriaan van Os


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


[fpc-pascal] How to avoid Copy

2023-12-29 Thread Amir--- via fpc-pascal

Hi all,

 I have a List of record, where the record has a WideString field.
  I have some code like the following:

function check(constref v: TMyRecord; data: TListOfMyRecord): Boolean;
var
  r: TMyRecord;

begin
  Result := False;
  for r in data do
    if r.State = v.State then
  Exit(True);
end;

I call this method a lot and the CPU profiling shows a lot of cpu time 
spent on "fpc_copy_proc" (which I assume is doing the deep copy on 
records) from "TCustomListEnumerator.GetCurrent".
I considered other alternatives like using enumerators but they all need 
a to return a record (and hence copying the widestring field).
I can think of two solutions to get rid of the wasting(!) so much time 
on "fpc_copy_proc":
1) Changing the TMyRecord to TMyClass. But then I need to Create and 
Free a "lot" of objects.
2) Update TListOfMyRecord to TListOfPointerToMyRecord. This requires a 
"lot" of memory allocation/fragmentation.


Is there a better solution?

Best,
Amir
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Read Field names from VMT

2023-12-27 Thread Amir via fpc-pascal
Thank you!On Dec 27, 2023 7:46 AM, Sven Barth via fpc-pascal  wrote:

Am 26.12.2023 um 21:29 schrieb Amir---
  via fpc-pascal:


  
  
  On 12/26/23 01:14, Sven Barth via
fpc-pascal wrote:
  
  


  

  Amir--- via fpc-pascal
<fpc-pascal@lists.freepascal.org>
schrieb am Di., 26. Dez. 2023, 07:03:
  
  Hi,

   I want to retrieve the name of the fields in a
record/class, at run 
time. It looks like "TVmt.vFieldTable" is what I need.
But I cannot find 
any documentation about how to explore the content of
this table. I 
appreciate any pointer.
  

  
  
  
  This only works for published fields and only
fields of type class or interface can be published. 
  

  
  That would work for me. How can I enumerate over those fields?

You can use the PVmtFieldTable and PVmtFieldEntry types from the
TypInfo unit:

=== code begin ===

program tfield;

{$mode objfpc}{$H+}

uses
  TypInfo;

type
  {$M+}
  TSub = class

  end;

  TTest = class
  published
    fTest: TSub;
  end;

var
  vft: PVmtFieldTable;
  vfe: PVmtFieldEntry;
  i: SizeInt;
begin
  vft := PVmtFieldTable(PVMT(TTest)^.vFieldTable);
  Writeln(vft^.Count, ' field(s) with ', vft^.ClassTab^.Count, '
type(s)');
  for i := 0 to vft^.Count - 1 do begin
    vfe := vft^.Field[i];
    Writeln(i, ' -> ', vfe^.Name, ' @ ', vfe^.FieldOffset, ' of
type ', vft^.ClassTab^.ClassRef[vfe^.TypeIndex - 1]^.ClassName);
  end;
end.

=== code end ===

=== output begin ===

PS C:\fpc\git> .\testoutput\tfield.exe
1 field(s) with 1 type(s)
0 -> fTest @ 8 of type TSub

=== output end ===

Side note: contrary to what I had originally written only classes,
but not interfaces are allowed for published fields and they need to
have $M enabled.

Regards,
Sven
  
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Read Field names from VMT

2023-12-26 Thread Amir--- via fpc-pascal


On 12/26/23 01:14, Sven Barth via fpc-pascal wrote:
Amir--- via fpc-pascal  schrieb am 
Di., 26. Dez. 2023, 07:03:


Hi,

   I want to retrieve the name of the fields in a record/class, at
run
time. It looks like "TVmt.vFieldTable" is what I need. But I
cannot find
any documentation about how to explore the content of this table. I
appreciate any pointer.


This only works for published fields and only fields of type class or 
interface can be published.

That would work for me. How can I enumerate over those fields?

Best,
Amir

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


[fpc-pascal] Read Field names from VMT

2023-12-25 Thread Amir--- via fpc-pascal

Hi,

  I want to retrieve the name of the fields in a record/class, at run 
time. It looks like "TVmt.vFieldTable" is what I need. But I cannot find 
any documentation about how to explore the content of this table. I 
appreciate any pointer.


Thank you,
Amir
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] I'm working on automated Help Output for console apps

2020-11-20 Thread Amir via fpc-pascal

Hi,

 I also have a similar library for that purpose:

https://github.com/AmirAavani/my-units/blob/master/General-Purpose-Units/ParameterManagerUnit.pp

This library expects "ValidArguments.inc" file whose content is like the 
following:


ValidArgumentsInfo : array of AnsiString = ('--InputFile:AnsiString', 
'--Debug:Boolean');

ValidArgumentsValues : array of AnsiString = ('', 'True');

The second array, ValidArgumentsValue (which should be renamed to 
DefaultValues) set the default values, if none provided.


Amir

On 11/20/20 2:38 AM, Benito van der Zander via fpc-pascal wrote:

Hi,

I also made such a thing:

var optionsreader: TCommandLineReader;
begin
  optionsreader := TCommandLineReader.create;

  optionsreader.declareFile('file', 'The file to be processed');
  optionsreader.addAbbreviation('f');

  optionsreader.declareFlag('help', '');
  optionsreader.addAbbreviation('h');

  optionsreader.declareFlag('version', 'Print the version of the 
application');

  optionsreader.addAbbreviation('v');

  if optionsreader.existsProperty('help') then
     writeln(optionsreader.availableOptions);

end.


Output:

--file=  or -f    The file to be processed
--help or -h
--version or -v     Print the version of the application


You can download it at http://www.benibela.de/sources_en.html#rcmdline

Benito

On 20.11.20 01:33, Graeme Geldenhuys via fpc-pascal wrote:

Hi,

I'm working on a automated help output writer(s) for console apps.
Thus no more tedious and ugly output when you do: myapp -h

My aims:
  * I write a lot of console apps, so this would be very useful to me.
  * Ability to swap out the help formatter. It's interface based, so
custom implementations can easily be created.
  * Auto align help options and descriptions - the most annoying thing to
do manually. ;-)
  * Ability to define console width in which to format and wrap the help
output, but has a default value.
  * The idea is loosely base on the Java version found in Apache Commons.

When it's done I'll obviously shared it as open source somewhere.

With that said, below is how I currently use it. It uses the Builder design
pattern so gives it the Chain Invocations syntax. I know it's not something
often seen in Pascal programs, but it makes it very easy to read and easy
to use/type, especially with code completion editors like Lazarus IDE.

For those console programmers out there... Is there anything in console help
output that you like or wish you had. That way I could possibly add it and
make this even more useful to a wider audience.

I'm still working on AppName, Version and Usage output.

Example code:
==
var
   optionlist: TOptions;
   helpFormatter: IHelpFormatter;
   header: string;
   footer: string;
begin
   optionlist := TOptions.Create;

   optionlist.add(TOption.Builder
 .isRequired
 .withDescription('The file to be processed')
 .hasArg
 .withArgName('file')
 .withLongOpt('file')
 .build('f'));// build() always takes the mandatory short 
option.

   optionlist.add(TOption.Builder
 .withLongOpt('help')
 .withArgName('test')  // this is ignored because .hasArg was not 
specified
 .build('h'));

   optionlist.add(TOption.Builder
 .withDescription('Print the version of the application')
 .withLongOpt('version')
 .build('v'));

   header := 'Do something useful with an input file' + LineEnding;
   footer := LineEnding + 'Please report issues athttp://example.com/issues';

   helpFormatter := TBasicHelpFormatter.Create();

   // sample outputs with increasing verbosity

   writeln('===   (1)');
   helpFormatter.printHelp(optionlist);

   writeln('===   (2)');
   helpFormatter.printHelp('DocView v1.0', optionlist);

   writeln('===   (3)');
   helpFormatter.printHelp('DocView v1.0', header, optionlist, footer);

   writeln('== the end =');
   optionlist.Free;
end;
==


And here is the example output for the 3 options so far:

===   (1)
* -f,--file The file to be processed
   -h,--help
   -v,--versionPrint the version of the application

* indicates required parameters
===   (2)
DocView v1.0
* -f,--file The file to be processed
   -h,--help
   -v,--versionPrint the version of the application

* indicates required parameters
===   (3)
DocView v1.0
Do something useful with an input file

* -f,--file The file to be processed
   -h,--help
   -v,--versionPrint the version of the application

* indicates required parameters

Please report issues athttp://example.com/issues
== the end =



Regards,
   Graeme



___
fpc-pascal maillist  -