Rosetta Stone
Introduction
Often, people new to a programming language/library have trouble mapping the things they know how to do in other environments to the new environments.
It can be handy to have a sort of "Rosetta stone" that roughly translates tasks from one environment/language into another.
Programming languages
If you have experience in other programming languages (such as C++, Visual Basic), there are some Rosetta stone web pages that might help you. As FreePascal/Lazarus syntax and library is fairly consistent with Delphi's, sites that "translate" to Delphi are also a valuable resource.
Some useful pages:
- http://mc-computing.com/Languages/ This page has some explanation of the concepts involved
- http://rosettacode.org/wiki/Category:Pascal A huge amount of languages, even esoteric, and tasks make this site special
Operating systems
If you know how to do something in an operating system, chances are you can do the same using FPC/Lazarus.
The table below gives a rough mapping of some tasks:
Windows/DOS | Unix/Linux | Description | FreePascal/Lazarus |
copy | cp | Copy file | Lazarus fileutil.copyfile; roll your own with filestreams |
date /t | date | Show current date | sysutils.now (date/time); sysutils.date (date); sysutils.time (time) |
del, erase | rm, rm -f | Delete file | sysutils.deletefile, erase |
deltree, rmdir /s | rm -r,rm -rf | Remove directories with subdirectories | Lazarus fileutil.deletedirectory |
dir | ls | Find files in a directory | Lazarus FindAllFiles |
diskpart list volume | mount | Show partitions/volumes/drives on a computer | Windows: see Windows_Programming_Tips#Listing_all_available_drives
Linux: see Linux_Programming_Tips#Get_the_list_of_mounted_partitions Unix: you'll have to parse some files (e.g. /etc/mtab) yourself, depending on Unix flavour; see Forum post |
find | grep | Search for a text/string | Several options, including the pos, ansipos. Regular expression support is provided by the RegExpr unit. |
ldifde | ldapsearch | Search through Active Directory/LDAP | Use Synapse ldapsend unit to work with LDAP queries; see e.g. example code on Leonardo Ramé's blog |
md5sum | md5sum | Calculate hash of file contents | You can use the MDFile function in the md5 FPC unit. |
mkdir | mkdir | Create directory | mkdir; forcedirectories (creates entire path, if necessary) |
move | mv | Move file to another directory | Within partition/disk: sysutils.renamefile; otherwise copy and delete original |
rename, ren | mv | Rename file | sysutils.renamefile (can also "move" a file between directories, but only on same partition/disk |
shutdown | shutdown | Shut down computer | ? |
wget, curl | wget, curl | Download file from HTTP/FTP | Multiple options, e.g. use synapse httpsend or ftpsend units: Synapse#Downloading_files |
? | which | Search for executable in path | Lazarus fileutil.FindDefaultExecutablePath |
Finding all occurrences of some bytes in a file
A sort of grep. From forum post by KpjComp: [1]
The block search class:
unit block_search;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, fgl;
type
{ TBlockSearch }
TBlockSearchResults = specialize TFPGList<int64>;
TBlockSearch = class
private
src:TStream;
fresults:TBlockSearchResults;
block:array of byte;
public
procedure SearchFor(a:array of byte);
constructor Create(_Src:TStream; blocksize:integer = 1024*1024);
destructor Destroy; override;
property Results:TBlockSearchResults read fResults;
end;
implementation
{ TBlockSearch }
procedure TBlockSearch.SearchFor(a: array of byte);
var
readsize:integer;
fPos:Int64;
fifoBuff:array of byte;
fifoSt,fifoEn,searchLen,lpbyte:integer;
//
procedure CheckPos;
var
l,p:integer;
begin
p := fifoST;
for l := 0 to pred(SearchLen) do
begin
if a[l] <> fifoBuff[p] then exit;
//p := (p+1) mod SearchLen, the if seems quicker
inc(p); if p >= SearchLen then p := 0;
end;
fresults.Add(fpos-searchLen);
end;
//
begin
fresults.clear;
src.Position:=0;
readsize := src.Read(block[0],Length(block));
searchLen := length(a);
if searchLen > length(block) then
raise Exception.Create('Search term larger than blocksize');
if readsize < searchLen then exit;
setlength(fifoBuff,searchLen);
move(block[0],fifoBuff[0],searchLen);
fPos:=0;
fifoSt:=0;
fifoEn:=SearchLen-1;
CheckPos;
while readsize > 0 do
begin
for lpByte := 0 to pred(readsize) do
begin
inc(fifoSt); if fifoSt>=SearchLen then fifoST := 0;
inc(fifoEn); if fifoEn>=SearchLen then fifoEn := 0;
fifoBuff[fifoEn] := block[lpByte];
inc(fPos);
CheckPos;
end;
readsize := src.Read(block[0],Length(block));
end;
end;
constructor TBlockSearch.Create(_Src: TStream; blocksize: integer);
begin
inherited Create;
setlength(block,blocksize);
src := _src;
fresults := TBlockSearchResults.Create;
end;
destructor TBlockSearch.Destroy;
begin
freeAndNil(fresults);
inherited Destroy;
end;
end.
Example of usage:
var
bs:TBlockSearch;
..
..
bs := TBlockSearch.Create(SourceFile);
try
bs.SearchFor(WhatIAmSearchingFor);
for i := 0 to bs.results.count-1 do
begin
// Example: we need to do something at an offset after the result
SourceFile.Position := bs.Results.Items[i] + 5;
SourceFile.ReadBuffer(RecordToParse, SizeOf(RecordToParse));
// And now I work on the data in the second packed record of arrays and output to memo or whatever
end;
finally
bs.free;
end;