-
Content Count
2699 -
Joined
-
Last visited
-
Days Won
115
Remy Lebeau last won the day on December 22
Remy Lebeau had the most liked content!
Community Reputation
1429 ExcellentTechnical Information
-
Delphi-Version
Delphi 12 Athens
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
-
Folder ReadOnly, Hidden, Normal
Remy Lebeau replied to Henry Olive's topic in RTL and Delphi Object Pascal
Nothing. ReadOnly has no meaning for a folder and is ignored. This is documented behavior: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileattributesw Making a folder read-only is an illusion. When you do it in Explorer, it iterates the folder's files and updates them accordingly. You can't change the attribute on the folder itself. Doing so is reserved by Windows for its private use on system folders. You cannot view or change the Read-only or the System attributes of folders in Windows Server 2003, in Windows XP, in Windows Vista or in Windows 7 -
Case: Please Explain Why Inline Variable Prevents Compilation
Remy Lebeau replied to rgdawson's topic in RTL and Delphi Object Pascal
Show off 😉 Thanks, I have added it to the bug report. -
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
Remy Lebeau replied to bravesofts's topic in Algorithms, Data Structures and Class Design
That is not what I would call a MINIMAL example, but at least it compiles this time. There is still a lot of IRRELEVANT code that has nothing at all to do with demonstrating the issue at hand. But so be it. Your TBaseConnectionParams and TSqliteParams classes are duplicating similar code because THEY ARE RETURNING DIFFERENT THINGS, so how to do you expect one to just inherit the behavior of the other? They can't. If you really want to make use of class inheritance then you need to simplify the design of the common elements so they are coherent and overridable across descendants. You are not even override'ing the base methods, you are reintroduce'ing them. That is not how inheritance works.- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
@David Heffernan who are you directing that to?
-
You don't need to change the AppType to use WriteLn(). A GUI app can simply call AllocConsole() or AttachConsole() and then WriteLn() will automatically work. That being said, another way to debug would be to use OutputDebugString() instead, and then you can see the messages in the IDE's debugger, or in SysInternals DebugView when running outside of the debugger.
-
Case: Please Explain Why Inline Variable Prevents Compilation
Remy Lebeau replied to rgdawson's topic in RTL and Delphi Object Pascal
I can reproduce the problem in a simple example that doesn't involve Spring4D (however, I get an "E2010 Incompatible types" error instead of an E2250) : type IShared<T> = reference to function: T; Shared = class class function Make<T: class>(AObj: T): IShared<T>; end; TSharedImpl<T: class> = class(TInterfacedObject, IShared<T>) FObj: T; constructor Create(AObj: T); destructor Destroy; override; function Invoke: T; end; TTest = class end; TTester = class procedure DoTest(AObj: TTest); end; class function Shared.Make<T>(AObj: T): IShared<T>; begin Result := TSharedImpl<T>.Create(AObj) as IShared<T>; end; constructor TSharedImpl<T>.Create(AObj: T); begin inherited Create; FObj := AObj; end; destructor TSharedImpl<T>.Destroy; begin FObj.Free; inherited Destroy; end; function TSharedImpl<T>.Invoke: T; begin Result := FObj; end; procedure TTester.DoTest(AObj: TTest); begin //... end; procedure Foo1; var Tester : IShared<TTester>; TestObj : IShared<TTest>; begin Tester := Shared.Make(TTester.Create); TestObj := Shared.Make(TTest.Create); Tester.DoTest(TestObj); // <-- Compiles OK! end; procedure Foo2; begin var Tester: IShared<TTester>; var TestObj: IShared<TTest>; Tester := Shared.Make(TTester.Create); TestObj := Shared.Make(TTest.Create); Tester.DoTest(TestObj); // <-- E2010 Incompatible types: 'TTest' and 'IShared<TTest>' Tester.DoTest(TestObj()); // <-- Compiles OK! end; I have now reported this issue to Embarcadero: RSS-2613: Anonymous Method is called differently depending on whether it is declared as an Inline Variable or not -
Just like in the example I gave you in my last reply, in this case I'm guessing that R.Name[10] is 0x0065 (Latin Small Letter E) and R.Name[11] is 0x0301 (Combining Acute Accent), whereas you are expecting R.Name[10] to be 0x00E9 (Latin Small Letter E with Acute) instead. To accomplish what you want, you should normalize the Unicode characters, probably to form NFC, before you can then process and replace them. Read the following for more details: Unicode Standard Annex #15: Unicode Normalization Forms Using Unicode Normalization to Represent Strings NormalizeString function I realize that. But that is reserved for markup language in plain text. You need to actually click on the '</>' button in the toolbar and put your code in the resulting popup dialog.
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
Remy Lebeau replied to bravesofts's topic in Algorithms, Data Structures and Class Design
I'm sorry, but the code you have provided is full of errors, I can't even attempt to compile it as-is, and I'm not going to waste my time trying to fix it all. When you can provide an example that can be COPY/PASTED as-is (or better, provide the actual files as attachments), and it can compile and produce a specific compiler error that you are trying to fix, then I will be happy to look at it again.- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
One issue I see is you are not taking into account either UTF-16 surrogates, or Unicode combining codepoints. Not all Unicode characters take up 1 WideChar, sometimes they require 2+ WideChars, especially if they are not in a normalized form. For example, the character 'á' may be 1 WideChar 0x00E1 (Latin Small Letter A with Acute), or it may be 2 WideChars 0x0061 (Latin Small Letter A) and 0x0301 (Combining Acute Accent) working together. What are the actual numeric values of the WideChars that you are actually receiving for the filename you are having trouble with? That is because you are posting the code as plain text. Put it inside of a code block instead (the '</>' button on the editor toolbar). For example: void sayHi() { cout << "This is in a code block!"; }
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
Remy Lebeau replied to bravesofts's topic in Algorithms, Data Structures and Class Design
Can you trim that down to a MINIMAL example that actually exhibits the problem? Most of that code is irrelevant to the issue. Are you getting a compiler error? If so, what is it? What EXACTLY are you trying to implement that you think is missing?- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
Remy Lebeau replied to bravesofts's topic in Algorithms, Data Structures and Class Design
Any class that derives from TBaseFoo inherits the methods that TBaseFoo implements. Why do you think any workaround is needed? What is the actual PROBLEM you are having with your code in the first place?- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
Feel free to step into the RTL source code for yourself with the debugger (see the code below). On Windows, the RTL's Find(First|Next)() functions simply call the API Find(First|Next)FileW() functions and then copy the WIN32_FIND_DATA fields into the TSearchRec fields: function FindFirstFile; external kernelbase name 'FindFirstFileW'; function FindNextFile; external kernelbase name 'FindNextFileW'; ... function FindMatchingFile(var F: TSearchRec): Integer; ... begin while F.FindData.dwFileAttributes and F.ExcludeAttr <> 0 do if not FindNextFile(F.FindHandle, F.FindData) then begin Result := GetLastError; Exit; end; ... F.Name := F.FindData.cFileName; // <-- HERE Result := 0; end; function FindFirst(const Path: string; Attr: Integer; var F: TSearchRec): Integer; const faSpecial = faHidden or faSysFile or faDirectory; begin F.ExcludeAttr := not Attr and faSpecial; F.FindHandle := FindFirstFile(PChar(Path), F.FindData); if F.FindHandle <> INVALID_HANDLE_VALUE then begin Result := FindMatchingFile(F); // <-- HERE if Result <> 0 then FindClose(F); end else Result := GetLastError; end; function FindNext(var F: TSearchRec): Integer; begin if FindNextFile(F.FindHandle, F.FindData) then Result := FindMatchingFile(F) // <-- HERE else Result := GetLastError; end; As you can see, the API's WIN32_FIND_DATA::cFileName is assign as-is to the RTL's TSearchRec::Name field, and since both field are based on WideChar (WIN32_FIND_DATA::cFileName is a WideChar[] array and TSearchRec::Name is a UnicodeString) then there is no manipulation of the reported characters in any way, they are copied as-is. What you get back in your code SHOULD be exactly what Windows actually reported. The TSearchRec::FindData field is the raw WIN32_FIND_DATA data that Find(First|Next)File() actually reported.
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
Remy Lebeau replied to bravesofts's topic in Algorithms, Data Structures and Class Design
The TTestFoo class inherits all of the implemented methods of the TBaseFoo class. This is literally how class inheritance works. I don't understand the question. However, interface inheritance works a little different. Sometimes you have to make sure that a derived class explicitly declares all of the interfaces it supports - even the base ones - and not rely on inheritance alone to do that for you, eg: TTestFoo = class(TBaseFoo, IBaseFoo, ITestFoo) // automatically inherits the methods of TBaseFoo... procedure TestFooMethod; end;- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
The RTL's Find(First|Next)() functions use the Win32 Find(First|Next)FileW() APIs internally, and have done so since 2009. That might be related to the removal of the Form's OldCreateOrder property in RAD Studio 11. But, you should never have been using the OnCreate (and OnDestroy) event(s) in C++ anyway, as that has always had the potential of introducing Undefined Behavior in user C++ code due to the different creation models between Delphi vs C++. Use the Form's constructor (and destructor) instead, that is always safe. And streamed property values are available in the constructor.
-
How to solve System Out of Resources in TScrollBox
Remy Lebeau replied to araujoarthur's topic in VCL
For my custom log viewer, I used a standard TListView in virtual mode with owner-drawn items, and it handles millions of items (GB-sized log files) just fine with low overhead. The hardest part was implementing a caching mechanism for the on-screen items, as I also filter and search items so don't want to keep the whole file in memory at one time.