Recent

Author Topic: [SOLVED] Generics: list of string,string,string  (Read 11554 times)

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
[SOLVED] Generics: list of string,string,string
« on: December 30, 2013, 01:16:12 pm »
Hi all,

Is there a way to have a generic list with, say, 3 strings, making it some sort of array?

I have to store
SourceURL
OperatingSystem
FileName

for some files I'm going to download depending on OS.

As a fallback, I suppose I could set up a record containing 3 strings and use that in some generics list but if there's an easier way, I'm all ears!

Thanks
BigChimp
« Last Edit: January 09, 2014, 01:59:52 pm by BigChimp »
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

BlueIcaro

  • Hero Member
  • *****
  • Posts: 834
    • Blog personal
Re: Generics: list of string,string,string
« Reply #1 on: December 30, 2013, 03:41:07 pm »
Try to make a Object with your record
Code: Pascal  [Select][+][-]
  1. Type TMyrecord = Class
  2. SourceURL : string;
  3. OperatingSystem : string
  4. FileName string;
  5. end;
  6.  
Then make a new Object with TList of your Object, like this:
Code: Pascal  [Select][+][-]
  1.  
  2. Type TMyList = Class
  3.  fList : TList;
  4. public
  5.  Constructor Create;
  6.  Property Add (aItem : TMyRecord);
  7.  Function Item (Index:integer):TMyRecord;
  8. end;
  9.  
This is a Fast example write on fly, but may be you can undertand what I want to explain.

Other way can be use TCollections
http://www.freepascal.org/docs-html/rtl/classes/tcollection.html

Well this is my ideas, I'm not a "pro" only a hobbie programer. May there is better ideas.

/BlueIcaro


BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Generics: list of string,string,string
« Reply #2 on: December 30, 2013, 04:25:05 pm »
Thanks, BlueIcaro, that's certainly a possible approach.

Let's see if the "mean and lean" generics masters have something to say :)

Regards,
A fellow hobby programmer ;)
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
Re: Generics: list of string,string,string
« Reply #3 on: December 30, 2013, 05:28:00 pm »
How many records do you expect (magnitude), and do you need ordering?

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Generics: list of string,string,string
« Reply #4 on: December 30, 2013, 05:35:49 pm »
About 30, perhaps 100 at most. Ordering is not necessary (would be nice based on one of the strings).
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Generics: list of string,string,string
« Reply #5 on: December 30, 2013, 05:49:04 pm »
(Although using an array could of course also work, I'm interested in generics in case I have something like <string,string,integer>... in my case, the OS could be an enumerated type or whatever it's called in Pascal)
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

vfclists

  • Hero Member
  • *****
  • Posts: 1165
    • HowTos Considered Harmful?
Re: Generics: list of string,string,string
« Reply #6 on: January 02, 2014, 10:47:58 am »
The better question might be are the some code samples featuring generics with some examples of how certain things done in regular old Pascal are better implemented with generics?

Some of us haven't used any of the new language features added since Delphi 7.
Lazarus 3.0/FPC 3.2.2

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Generics: list of string,string,string
« Reply #7 on: January 02, 2014, 12:50:23 pm »
My understanding is that generics help when dealing with a variety of simple types in a generic way, but are not so readily applied to complex or structured types.
Here is one way to encapsulate your string data. You would probably want to add better error-checking, and ways to locate, sort and delete on individual data such as a particular operating system; but I don't know what your requirements are for that.

Code: [Select]
unit main3StringList;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Grids, strutils;

type

  { T3stringList }

  T3stringList = class(TStringList)
  private
    FInnerDelim: AnsiChar;
    FInnerDelimiter: AnsiChar;
    function GetFileName(index: integer): AnsiString;
    function GetOS(index: integer): AnsiString;
    function GetSourceURL(index: integer): AnsiString;
    function Parse3String(const s: string; var URL, OS, FName: AnsiString): boolean;
  public
    constructor Create(anInnerDelimiter: AnsiChar);
    procedure Add3String(const aSource, anOs, aFileName: ansistring);
    property InnerDelimiter: AnsiChar read FInnerDelimiter;
    property SourceURLs[index: integer]: AnsiString read GetSourceURL;
    property OSs[index: integer]: AnsiString read GetOS;
    property FileNames[index: integer]: AnsiString read GetFileName;
  end;

  { TForm1 }

  TForm1 = class(TForm)
    grid: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    threeSL: T3stringList;
  end;

var
  Form1: TForm1;

implementation

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  threeSL:=T3stringList.Create(#11);
  threeSL.Add3String('www.freepascal.org','linux','/home/etc/some');
  threeSL.Add3String('www.blaisepascal.eu','Windows','C:\autoexec.bat');
  threeSL.Add3String('www.embarcadero.com','Mac OS X','file name3');
  grid.ColCount:=3;
  grid.RowCount:=threeSL.Count;
  for i:=0 to threeSL.Count-1 do begin
    grid.Cells[0,i]:=threeSL.SourceURLs[i];
    grid.Cells[1,i]:=threeSL.OSs[i];
    grid.Cells[2,i]:=threeSL.FileNames[i];
  end;
  grid.AutoSizeColumns;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  threeSL.Free;
end;

{$R *.lfm}

{ T3stringList }

function T3stringList.GetFileName(index: integer): AnsiString;
var
  url, os: AnsiString;
begin
  if not ( (index>=0) and (index<Count) and
    Parse3String(Self[index],url, os, Result) )
  then Result:='';
end;

function T3stringList.GetOS(index: integer): AnsiString;
var
  url, fname: AnsiString;
begin
  if not ( (index>=0) and (index<Count) and
    Parse3String(Self[index],url, Result, fname) )
  then Result:='';
end;

function T3stringList.GetSourceURL(index: integer): AnsiString;
var
  os, fname: AnsiString;
begin
  if not ( (index>=0) and (index<Count) and
    Parse3String(Self[index], Result, os, fname) )
  then Result:='';
end;

function T3stringList.Parse3String(const s: string; var URL, OS, FName: AnsiString): boolean;

  function DelimCount: integer;
  var
    c: AnsiChar;
  begin
    Result:=0;
    for c in s do
      if (c = FInnerDelimiter) then
        Inc(Result);
  end;

var
  p1, p2: integer;
begin
  if (DelimCount <> 2) then
    Exit(False);
  p1:=Pos(FInnerDelimiter, s);
  url:=Copy(s, 1, Pred(p1));
  p2:=PosEx(FInnerDelimiter, s, Succ(p1));
  OS:=Copy(s, Succ(p1), Pred(p2-p1));
  FName:=Copy(s, Succ(p2), maxint);
  Result:=True;
end;

constructor T3stringList.Create(anInnerDelimiter: AnsiChar);
begin
  inherited Create;
  FInnerDelimiter:=anInnerDelimiter;
end;

procedure T3stringList.Add3String(const aSource, anOs, aFileName: ansistring);
begin
  Add(Format('%s%s%s%s%s',[aSource,FInnerDelimiter,anOs,FInnerDelimiter,aFileName]));
end;

end.


marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
Re: Generics: list of string,string,string
« Reply #8 on: January 02, 2014, 12:55:51 pm »
The notation <x,y> is usually meant for a  <key,value> map.

So the next question would mean what really is a <string,string,string> ?  Do you want it to create 3 arrays? Have one array, but three indexes into, which each item as a string.

(though with cardinality 30, I doubt it matters :-)

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Generics: list of string,string,string
« Reply #9 on: January 04, 2014, 02:18:41 pm »
Thanks guys - Howard, I'll have a look, that code looks nice.

@Marco: I think I remembered the notation from .net, where it is possible to stuff quite some variables into a generic class.

Indexes etc doesn't really matter, you're right.
One "array" without any index but the strings (or other types) available for reference when accessing it would be fine.

Underlying goal:
- build a list of
1. URL
2. operating system (either as a string or enum),
3. optionally category (debug components, essential tools, optional tools=>e.g. in an enum)
4. local filename
5. optional status (non installed, downloaded, verified correct)

- when running, traverse this list and download what's needed depending on current O/S, components chosen; update status

(It's to simplify current processing in fpcup)
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12984
  • FPC developer.
Re: Generics: list of string,string,string
« Reply #10 on: January 04, 2014, 02:38:39 pm »
Thanks guys - Howard, I'll have a look, that code looks nice.

@Marco: I think I remembered the notation from .net, where it is possible to stuff quite some variables into a generic class.

My .NET experience is 7 years ago and slowly fading :-) (and generics were just "new" then to .NET)

It is possible, also in FPC to have more than two generic variables, but afaik at least in FPC/Delphi it doesn't define a container that way. So for that you need to define the record, and then use TList<therecord>
 
« Last Edit: January 04, 2014, 05:41:42 pm by marcov »

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: [SOLVED] Generics: list of string,string,string
« Reply #11 on: January 09, 2014, 02:02:04 pm »
In the end, I followed vfclists and  used this despite my predilection for providing off by one errors:
Code: [Select]
type
  TUtilCategory = (ucBinutil {regular binutils like as.exe},
    ucDebugger {Debugger (support) files},
    ucQtFile {e.g. Qt binding},
    ucOther {unknown});

  // Keeps track of downloadable files, e.g. binutils
  TUtilsList= record
    FileName: string;
    //OS as determined by FPC (e.g. WIN32). Blank for all
    OS: string; // For now, OS field is not used as compiler defines manage filling the initial list
    RootURL: string; //URL including trailing / but without filename
    Category: TUtilCategory;
  end;
...
//somewhere in a class:
    FUtilFiles: array of TUtilsList; //Keeps track of binutils etc download locations, filenames...

// setting up the list
  procedure AddNewUtil(FileName, RootURL, OS: string; Category: TUtilCategory);
  var
    i: integer;
  begin
    SetLength(FUtilFiles, 2+high(FUtilFiles)-low(FUtilFiles));
    i:=high(FUtilFiles);
    FUtilFiles[i].FileName:=FileName;
    FUtilFiles[i].RootURL:=RootURL;
    FUtilFiles[i].OS:=OS; //actually don't use OS yet; depend on conditional defines
    FUtilFiles[i].Category:=Category;
  end;
begin
  SetLength(FUtilFiles,0); //clean out any cruft
  {$IFDEF MSWINDOWS}
  // Common to both 32 and 64 bit windows (i.e. 32 bit files)
  AddNewUtil('cpp' + GetExeExt,SourceURL,'',ucBinutil);
...
//and using them:
  for Counter := low(FUtilFiles) to high(FUtilFiles) do
  begin
    if (FUtilFiles[Counter].Category=ucBinutil) or (FUtilFiles[Counter].Category=ucDebugger) then
    begin
      infoln('Downloading: ' + FUtilFiles[Counter].FileName + ' into ' + FMakeDir,etinfo);
      try
        if Download(FUtilFIles[Counter].RootURL + FUtilFiles[Counter].FileName,
          IncludeTrailingPathDelimiter(FMakeDir) + FUtilFiles[Counter].FileName,
          FHTTPProxyHost,
          inttostr(FHTTPProxyPort),
          FHTTPProxyUser,
          FHTTPProxyPassword) = false then
...
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

 

TinyPortal © 2005-2018