Delphi DEC CalcFile Message - delphi

I've just stared looking at the Delphi Encryption Compendium (I used GetIt to install v6.3 in Delphi 10.4.2)
Here is a simple procedure I have used to calc a File Hash
var
HASH : THash_SHA3_384;
s : rawbytestring;
begin
try
HASH := THash_SHA3_384.Create;
HASH.Init;
s := HASH.CalcFile(edFilename.Text,Tformat_HEX);
EdHashedFile.Text := s;
hash.Done;
finally
HASH.Free;
end;
end;
The resulting hash agrees with various online resources that calc a SHA3_384.
However a message box is displayed when it's doing the calc.
"Absorb: number of bits mod 8 <> 0 or squeezing active. Bits:0, Squeezing: True."
Don't know if it's important ?
if it is what do I do about it ?
if it isn't how do I supress it ?
Many thanks

Related

Unknown Runtime Error in delphi7, 'Invalid floating point operation.' No crash

Good day, I need advice on a piece of code I wrote. It is an activity from my delphi7 school textbook, so you can imagine I am still new to pascal.
My program works fine and gets the results I need, but I receive a strange:
" Invalid floating point operation" message in runtime without the program crashing. With my limited knowledge, I can't find the reason behind this error. It is confusing as I did not use any real numbers but please have a look.
Let me know if you need additional information
Thank you in advance, I am open to learning!
private
arrLearners : array of string;
arrMod : array of string;
procedure TfrmPortfolios.btnEnterClick(Sender: TObject);
var
numL,k,d,a : integer;
l :string;
begin
k:=0;
numL:=0;
repeat
numL := StrToInt(InputBox('Enter names','How many learners in Subject?
(Max 30):','30'));
until
numL<=30;
SetLength(arrLearners, numL);
for k:=0 to numL-1 do
begin
arrLearners[k]:='Student No'+IntToStr(k+1);
end;
k:=0;
d := numL div 5; //used to see for every which learner will go to moderation. I.e if d=3 then every third student.
if numL <=9 then // below 9, d=1 then it's every student anyways
begin
for k:=0 to NumL-1 do
begin
SetLength(arrMod,NumL);
arrMod[k]:=arrLearners[k];
end;
end
else
begin
a := numL div d;
SetLength(arrMod, a);
for k:=0 to a-1 do
begin
arrMod[k] := arrLearners[(k*d) +1];
end;
end;
k:=0;
redOutput.Lines.Add('Students sent for moderation:'+#13);
for k:=0 to numL-1 do
begin
l:= arrMod[k];
redOutput.Lines.Add(l);
end;
end;
Make sure you have enabled range checking and overflow checking options. You can enable them either globally or locally in the code using compiler directives {$R+,O+} Range check is a very useful thing - it can save you much time on debug weird issues.

Machine dependent results for OLE check of MSWord version

With this code to retrieve the version of the installed MS Word:
uses uses oleauto;
[...]
function TForm2.GetWordVersion:string;
const
wdDoNotSaveChanges = 0;
var
WordApp: OLEVariant;
WordVersion: variant;
begin
Try
WordApp := CreateOLEObject('Word.Application');
WordVersion := WordApp.version;
WordApp.Quit(wdDoNotSaveChanges);
except
on E: Exception do
begin
WordVersion := -1;
end;
End;
Result := wordversion;
end;
I get 140 on my machine, my colleague gets 14. Both are win7/Word2010 but I am in Italy he is in India.
Anyone knows about this?
Why different values?
Thanks
I'm guessing this is a decimal separator issue. Word returns the string '14.0' and then when you convert to integer the period is treated as a positional separator on one machine, and a decimal separator on another.
The solution is to stop converting to integer which I infer that you are doing in code that you have not shown.
I am inferring that from this comment:
I can convert it to string and use the first 2 chars.
Since the code in the question operates on strings, I conclude that other code, not shown in the question, is converting to integer.

How can I find out how much memory is used by a specific component or class?

Is it possible to retrieve the amount of memory that is used by a single component in delphi?
I'm downloading simple strings from the internet and I see that the memory usage is up to a gigabyte at by the end of the downloading process, but when I look at the saved file which contains everything I downloaded the file is only in the kilobyte range, clearly there is something going on with the components, even though I destroy them.
Example:
Edit:
procedure TForm1.OnCreate(Sender: TObject);
var list: TStringList;
begin
list:=TStringList.Create;
list.LoadFromFile('10MB_of_Data.txt');
list.destroy;
end;
How can I know that "list" as a TStringList is using 10 MB worth of space in memory?
Thank you.
I think comparing the memory usage before and after is the way to go with this as there is no simple way of seeing what memory was allocated by a block of code after the fact... For example, with the string list above, the class itself will only take up a small amount of memory as it is made up of pointers to other allocations (i.e. the array of strings) and that itself is an array of pointers to to the actual strings... and this is a comparatively simple case.
Anyway, this can be done with FastMM with a function like follows...
uses
FastMM4;
function CheckAllocationBy(const AProc: TProc): NativeUInt;
var
lOriginalAllocated: NativeUInt;
lFinalAllocated: NativeUInt;
lUsage: TMemoryManagerUsageSummary;
begin
GetMemoryManagerUsageSummary(lUsage);
lOriginalAllocated := lUsage.AllocatedBytes;
try
AProc;
finally
GetMemoryManagerUsageSummary(lUsage);
lFinalAllocated := lUsage.AllocatedBytes;
end;
Result := lFinalAllocated - lOriginalAllocated;
end;
And can be used like so...
lAllocatedBytes := CheckAllocationBy(
procedure
begin
list:=TStringList.Create;
list.LoadFromFile('10MB_of_Data.txt');
list.Free;
end);
This will tell you how much your string list left behind (which interestingly I get 40 bytes for on the first run of repeated calls and 0 after which after consulting the usage logs before and after the call is two encoding classes created on the first call). If you want to check where leaked memory was allocated, it's simple to use FastMM to do that also (although I agree with the above that if it's 3rd party, it shouldn't be your problem).
First of all: please, be patient, this is actually not exactly answer for your question, but it is too large for posting it in comment. This code was written and compiled using FPC, but it can give some estimations for you. May be somebody knows how to port it to the Delphi.
program project4;
uses
SysUtils,
Classes;
var
p: Pointer;
sl: TStringList;
var
a: TFPCHeapStatus;
begin
a := GetFPCHeapStatus;
writeln('== 1 ==');
//writeln(a.MaxHeapSize);
writeln(a.MaxHeapUsed);
//writeln(a.CurrHeapSize);
writeln(a.CurrHeapUsed);
//writeln(a.CurrHeapFree);
GetMem(p, 1024);
a := GetFPCHeapStatus;
writeln('== 2 ==');
writeln(a.MaxHeapUsed);
writeln(a.CurrHeapUsed);
sl := TStringList.Create;
a := GetFPCHeapStatus;
writeln('== 3 ==');
writeln(a.MaxHeapUsed);
writeln(a.CurrHeapUsed);
sl.Add('To beer or not to beer? That is the question!');
a := GetFPCHeapStatus;
writeln('== 4 ==');
writeln(a.MaxHeapUsed);
writeln(a.CurrHeapUsed);
Readln;
end.
and output:
== 1 ==
2448
2448
== 2 ==
3488
3488
== 3 ==
3568
3568
== 4 ==
3616
3616
And another test with large text file:
sl.LoadFromFile('tolstoy - war and peace.txt');
a := GetFPCHeapStatus;
writeln('== 4 ==');
writeln(a.MaxHeapUsed);
writeln(a.CurrHeapUsed);
Output:
== 3 ==
3568
3568
== 4 ==
8837104
4643776
File size: 3,1 Mb (3 280 005 bytes) (ansi encoding)

Listing Filenames from a Directory with sorting? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to get the sort order in Delphi as in Windows Explorer?
I am trying to scan a directory, but I can't get it to Sort by File Name.
Example, say if I have these Filenames in a folder:
File1
File2
File3
File4
File5
File6
File7
File8
File9
File10
File11
File12
File13
File14
File15
File16
File17
File18
File19
File20
File21
File22
If I use something like this:
var
SL: TStringList;
SR: TSearchRec;
begin
SL := TStringList.Create;
try
if FindFirst(Path + '*.*', faAnyFile and not faDirectory and not faHidden, SR) = 0 then
repeat
SL.Add(Path + SR.Name)
until FindNext(SR) <> 0;
FindClose(SR);
// handle the filenames..
finally
SL.Free;
end;
end;
The result will be:
File10
File11
File12
File13
File14
File15
File16
File17
File18
File19
File2
File20
File21
File22
File3
File4
File5
File6
File7
File8
File9
It should be sorted by Filename (as I wrote in the first Filename list example).
I bet this is really simple but I cannot see it, what do I need to do to sort this?
Thanks.
You're starting with the assumption that there's some sort of inherent "order" for file names. There isn't. You appear to want the file names to be sorted alphabetically, with numerical portions of names sorted numerically. I'm not sure what you want to happen with punctuation and other characters.
The file-enumeration functions don't define any order that names will be returned in. They're returned in whatever order the underlying file system decides to provide them. There are two steps to getting a sorted list of file names. You're already doing the first one:
Collect the file names in a list for post-processing.
Arrange the names in the order you want. If plain "asciibetical" isn't what you want, then you can write a custom sorting function and pass it to TStringList.CustomSort.
For example, if you want them to be in the same order you see file names in Windows Explorer as of Windows XP, you can use the StrCmpLogicalW API function. Call that from your comparison function, like this:
function LogicalCompare(List: TStringList; Index1, Index2: Integer): Integer;
begin
Result := StrCmpLogicalW(PWideChar(List[Index1]), PWideChar(List[Index2]));
end;
SL.CustomSort(LogicalCompare);
If you have something earlier than Delphi 2007, you'll need to do something about converting your strings to wide characters, at least for the duration of the sorting phase.
FindFirst() and FindNext() merely enumerate the files on the file system as-is. The files can be returned in any order. You have to sort the TStringList yourself afterwards, eg:
function SortFilesByName(List: TStringList; Index1, Index2: Integer): Integer;
var
FileName1, FileName2: String;
FileNumber1, FileNumber2: Integer;
begin
// assuming the files are all named "Path\File###.xxx",
// where "###" is the number to sort on...
FileName1 := ChangeFileExt(ExtractFileName(List[Index1]), '');
FileName2 := ChangeFileExt(ExtractFileName(List[Index1]), '');
FileNumber1 := StrToInt(Copy(FileName1, 5, MaxInt));
FileNumber2 := StrToInt(Copy(FileName2, 5, MaxInt));
Result := (FileNumber2 - FileNumber1);
end;
var
SL: TStringList;
SR: TSearchRec;
begin
SL := TStringList.Create;
try
if FindFirst(Path + '*.*', faAnyFile and (not faDirectory) and (not faHidden), SR) = 0 then
try
repeat
SL.Add(Path + SR.Name)
until FindNext(SR) <> 0;
finally
FindClose(SR);
end;
SL.CustomSort(SortFilesByName);
// handle the filenames..
finally
SL.Free;
end;
end;
Any simple sort system (such as the one windows uses to return you files and delphi uses for sorting) will sort alphabetically and then by number, but unless you pad your numbers with zeros
1 comes before 2 so
11 comes before 2 (in the same way that aa comes before b)
you either need to pad you numbers with zeros such as
filename001
filename010
filename020
for use the answer provided by Remy Lebeau - TeamB above which will pull out the number at the end of you filename and sort by that.

How to handle large String Grids?

I find that I might have to use a String Grid of less than 10 columns, but about 50k rows.
Experiments have showed it to be a very unresponsive CPU hog.
Any pointers?
Code or components?
Preferably Delphi (7) build in or TMS (for which I have a license) or FOSS (for commercial use).
Update: please don't just tell me to use Virtual Tree View, etc. Please tell me why, so that I can learn something. Thanks.
I don't think the problem came from adding this number to the TStringGrid.
Adding 100k rows took less than 1 second (700ms) (Not high end PC, just Dual Core).
procedure TForm1.btn1Click(Sender: TObject);
Const
arr : array[1..5] of string = ('One','Two','Three','Four','Five');
Rows = 100000;
var
I: Integer;
F,E : Integer;
begin
StringGrid1.RowCount := Rows;
F := GetTickCount;
for I := 0 to Rows do
begin
StringGrid1.Cells[1,I] := Arr[1] + IntToStr(I);
StringGrid1.Cells[2,I] := Arr[2]+ IntToStr(I);
StringGrid1.Cells[3,I] := Arr[3]+ IntToStr(I);
StringGrid1.Cells[4,I] := Arr[4]+ IntToStr(I);
StringGrid1.Cells[5,I] := Arr[5]+ IntToStr(I);
end;
E := GetTickCount;
ShowMessage(Inttostr(E-F));
end;
I think the slowness in your code, do you bring the data from database? if so this is will be the bottleneck of your code, also adding 50k to WHATEVER GRID to show for users called "Bad practice".
And it's hard to tell you why that's slow without showing any code.
The TListView component in virtual mode is recommended frequently (I have not tried it myself but it sounds rather easy to implement)
If you are interested in virtual treeview you should checkout the whole virtual treeview trunk from http://code.google.com/p/virtual-treeview/source/checkout. You will find Demos\Advanced subdirectory where and Demo application showing the virtual treeview functionality, for example how to use virtual treeview as a grid.
You need SVN to checkout the code from googlecode. If you have never used SVN download and install TortoiseSVN
You may want to look at Virtual Treeview, which is built for high volume:
http://www.delphi-gems.com/index.php?option=com_content&task=view&id=12&Itemid=38

Resources