Jump to content

Remy Lebeau

Members
  • Content Count

    3000
  • Joined

  • Last visited

  • Days Won

    135

Everything posted by Remy Lebeau

  1. Remy Lebeau

    REST Datasnap Server Accepting ECDH Ciphers

    It could happen if the app is running on Android 6+ where BoringSSL has replaced OpenSSL but might use the old OpenSSL .so filenames.
  2. Remy Lebeau

    Enable Discussions on github ?

    @Anders MelanderThanks I'll look into that. Indy has a lot of open issue tickets, I'm sure a good chunk of them could be discussions.
  3. Remy Lebeau

    REST Datasnap Server Accepting ECDH Ciphers

    Sorry I have no idea. I've never worked with Datasnap before and done know if/how it exposes access to configure Indy.
  4. Remy Lebeau

    Enable Discussions on github ?

    I went ahead and enabled Discussions on GitHub. We'll see how it works out. I'll still monitor this forum and others, of course.
  5. Remy Lebeau

    REST Datasnap Server Accepting ECDH Ciphers

    There are a few 3rd party GitHub repos that add OpenSSL 3.x/TLS 1.3 to Indy, including: https://github.com/MWASoftware/Indy.proposedUpdate https://github.com/JPeterMugaas/TaurusTLS
  6. When using VarSameValue(), you can get a conversion failure if the 2 Variants are not holding compatible types. This is even stated in the documentation: So, you should first make sure the 2 Variants have the same type before comparing their values. This is just logical to do anyway, since if you know they have different types then there is no point in wasting resources to compare the values. When I make these small changes to TTestComponent, the "Could not convert variant" error goes away: procedure TTestComponent.SetCheckedValue(const Value: Variant); begin if (VarType(FCheckedValue) <> VarType(Value)) or // <-- ADD THIS! (not VarSameValue(FCheckedValue, Value)) then begin FCheckedValue := Value; CheckedValueChanged(); end; end; function TTestComponent.IsCheckedValueStored: Boolean; begin Result := (VarType(FCheckedValue) <> varBoolean) or // <-- ADD THIS! (not VarSameValue(FCheckedValue, True)); end; Now, that just leaves the problem of the 'CheckedValue.Type' property displaying "Unknown" for string values. That is indeed a bug in the default Variant property editor, which I have now reported to Embarcadero: RSS-2844; TVariantTypeProperty is broken for string values You can easily work around the bug, either directly in your component's property setter: procedure TTestComponent.SetCheckedValue(const Value: Variant); begin if (VarType(FCheckedValue) <> VarType(Value)) or (not VarSameValue(FCheckedValue, Value)) then begin FCheckedValue := Value; if VarType(FCheckedValue) = varString then FCheckedValue := VarToStr(Value); // <-- change the VarType to varUString CheckedValueChanged(); end; end; Or by deriving a custom property editor in your component's design-time package (if you don't have one, make one) to fix the bug directly: uses Variants, DesignIntf, DesignEditors, DesignConst; //... { TMyVariantTypeProperty } // unfortunately, TVariantTypeProperty is hidden in the implementation // of the DesignEditors unit, so we have to copy the entire class just // to change a couple of lines! const VarTypeNames: array[varEmpty..varInt64] of string = ( 'Unassigned', // varEmpty 'Null', // varNull 'Smallint', // varSmallint 'Integer', // varInteger 'Single', // varSingle 'Double', // varDouble 'Currency', // varCurrency 'Date', // varDate 'OleStr', // varOleStr '', // varDispatch '', // varError 'Boolean', // varBoolean '', // varVariant '', // varUnknown '', // [varDecimal] '', // [undefined] 'Shortint', // varShortInt 'Byte', // varByte 'Word', // varWord 'LongWord', // varLongWord 'Int64'); // varInt64 type TMyVariantTypeProperty = class(TNestedProperty) public function AllEqual: Boolean; override; function GetAttributes: TPropertyAttributes; override; function GetName: string; override; function GetValue: string; override; procedure GetValues(Proc: TGetStrProc); override; procedure SetValue(const Value: string); override; end; function TMyVariantTypeProperty.AllEqual: Boolean; var i: Integer; V1, V2: Variant; begin Result := False; if PropCount > 1 then begin V1 := GetVarValue; for i := 1 to PropCount - 1 do begin V2 := GetVarValueAt(i); if VarType(V1) <> VarType(V2) then Exit; end; end; Result := True; end; function TMyVariantTypeProperty.GetAttributes: TPropertyAttributes; begin Result := [paMultiSelect, paValueList, paSortList]; end; function TMyVariantTypeProperty.GetName: string; begin Result := 'Type'; end; function TMyVariantTypeProperty.GetValue: string; begin case VarType(GetVarValue) and varTypeMask of Low(VarTypeNames)..High(VarTypeNames): Result := VarTypeNames[VarType(GetVarValue) and varTypeMask]; varString,varUString: // <-- FIX HERE! Result := SString; else Result := SUnknown; end; end; procedure TMyVariantTypeProperty.GetValues(Proc: TGetStrProc); var i: Integer; begin for i := 0 to High(VarTypeNames) do if VarTypeNames[i] <> '' then Proc(VarTypeNames[i]); Proc(SString); end; procedure TMyVariantTypeProperty.SetValue(const Value: string); function GetSelectedType: Integer; var i: Integer; begin Result := -1; for i := 0 to High(VarTypeNames) do if VarTypeNames[i] = Value then begin Result := i; break; end; if (Result = -1) and (Value = SString) then Result := varUString; // <-- FIX HERE! end; var NewType: Integer; V: Variant; begin NewType := GetSelectedType; case NewType of varEmpty: VarClear(V); varNull: V := NULL; -1: raise EDesignPropertyError.CreateRes(@SUnknownType); else V := GetVarValue; // <-- move here for good measure... try VarCast(V, V, NewType); except { If it cannot cast, clear it and then cast again. } VarClear(V); VarCast(V, V, NewType); end; end; SetVarValue(V); end; { TMyVariantProperty } // fortunately, TVariantProperty is public in the DesignEditors unit, // so we need to override only 1 method in it... type TMyVariantProperty = class(TVariantProperty) procedure GetProperties(Proc: TGetPropProc); override; end; procedure TMyVariantProperty.GetProperties(Proc: TGetPropProc); begin Proc(TMyVariantTypeProperty.Create(Self)); end; procedure Register; begin //... // change the 2nd and 3rd properties if you want to reuse this editor for all Variant properties, eg: // RegisterPropertyEditor(TypeInfo(Variant), nil, '', TMyVariantProperty); RegisterPropertyEditor(TypeInfo(Variant), TTestComponent, 'CheckedValue', TMyVariantProperty); end;
  7. Not directly by Close() itself, no. But after Close() sets the ModalResult to mrCancel, the modal loop will then trigger the OnClose event to see if the ModalResult needs to be updated. Right, because ModalResult has already been set to non-zero before CloseModal() is called. CloseModal() gets the final decision on what ModalResult is set to before the loop evaluates it for termination. It actually is. The OnClose event is triggered whether the user clicks on the X button or on the Close system menu, or the code calls Close() or sets the ModalResult.
  8. Remy Lebeau

    Could not load OpenSSL library.

    In theory, Embarcadero is supposed to be using a private copy of Indy for their technologies, like DataSnap, where the IPPeer... units are part of an abstraction layer that interacts with that copy. And then users are supposed to be able to freely update the public version of Indy for their own projects without affecting that private layer. But in practice, things don't always work out that way.
  9. Delphi has no concept of OneDrive. It is merely using your user profile's standard Documents folder to store your project files, 3rd party packages, etc. But OneDrive has taken over your Documents folder and is storing it remotely. That is not Delphi's fault. If you don't like this, then either configure OneDrive to leave your Documents folder alone, or else configure Delphi's environment settings to use different folders that OneDrive doesn't touch.
  10. Remy Lebeau

    Memory leak on parsing json

    Before freeing the TJSONObject, can you verify that all of its child objects are set to Owned=True? Also, do you have the same problem if you try with FASTMM5 instead of FASTMM4?
  11. Remy Lebeau

    Memory leak on parsing json

    That alone should not be creating memory leaks. Just having FastMM enabled should not be accounting for a 20MB increase in memory usage. And, although FastMM does cache freed memory for later reuse, which can appear as a leak from Task Manager's POV but really isn't, it should not be reported as a leak during process shutdown. Only real leaks (ie unfreed allocations) should be reported as leaks. Can you provide the actual leak report? And, do you have tracing enabled so the report shows details about the code that allocated the leaked memory?
  12. And vice versa. But doing so works safely and reliably only if you stick to certain rules to ensure compatibility across programming languages/ABIs, environments, etc. Which limits what you can and can't use across the DLL boundary.
  13. Indy's TIdHTTP component supports Digest, just make sure the IdAuthenticationDigest unit is in your uses clause (directly, or via the IdAllAuthentications unit) . And then you can set the TIdHTTP.Request.Username and TIdHTTP.Request.Password as needed.
  14. Remy Lebeau

    TListView - manually adding items faster at runtime

    Can you provide an small example/steps that reproduces this problem? How to use Checkboxes in TListView (OwnerData True) in Delphi
  15. Remy Lebeau

    TListView - manually adding items faster at runtime

    Are you custom drawing the TListView? Virtual mode affects only data storage, so it should not cause drawing issues if you are otherwise using default settings.
  16. Remy Lebeau

    TListView - manually adding items faster at runtime

    That is correct.
  17. Remy Lebeau

    TListView - manually adding items faster at runtime

    For a non-trivial number of items, it is best to use the TListView in virtual mode. Set the OwnerData property to true, assign an OnData event handler, and then set the TListView.Items.Count property instead of using the TListView.Items.Add() method, eg: type TItemData = record LN: Integer; ItemNo: string; Desc: string; end; private lvItems: array of TItemData; procedure TForm1.btnAddClick(Sender: TObject); var Col : TListColumn; SW : TStopwatch; s : string; i : Integer; begin Col := lv1.Columns.Add; Col.Caption := 'LN'; Col.Alignment := taLeftJustify; Col.Width := 30; Col := lv1.Columns.Add; Col.Caption := 'ItemNo'; Col.Alignment := taLeftJustify; Col.Width := 60; Col := lv1.Columns.Add; Col.Caption := 'Desc'; Col.Alignment := taLeftJustify; Col.Width := 160; SetLength(lvItems, 25000); SetLength(ary,10); // create the array length (1,2,3,4,5,6,7,8,9,0) chars beep; SW := TStopWatch.StartNew; // start timing it for i := Low(lvItems) to High(lvItems) do begin ary := genRandValues; // generate random numbers ie (2,9,8,4,7,5,6,0,1,3) s := ListToStr(ary); // convert array list into a string var ie ('2984756013') lvItems[i].LN := i; lvItems[i].ItemNo := s; lvItems[i].Desc := s; end; lv1.Items.Count := Length(lvItems); SW.Stop; // finish timing eb1.Text := IntToStr(SW.ElapsedTicks) + ' ticks / ' + IntToStr(SW.ElapsedMilliseconds) + ' ms'; beep; end; procedure TForm1.lv1Data(Sender: TObject; Item: TListItem); begin Item.Caption := lvItems[Item.Index].LN.ToString(); // add the major field, ie 'LN', thus the populate with the index as line numbers Item.SubItems.Add(lvItems[Item.Index].ItemNo); // itemno ie '2984756013', and so on. Item.SubItems.Add(lvItems[Item.Index].Desc); // desc ie same, ... end;
  18. Remy Lebeau

    TDirectory - file lock out on Win 10 LTSC

    I don't trust the IOUtils unit. I feel it's functionality is bloated and error reporting is lacking/wonky. I prefer to stick with SysUtils::Find[First|Next]() or even ::Find[First|Next]File() directly. Have you tried that yet? Are there any error codes being reported when the problem happens? Similarly with std::[i|o]fstream, they lack good error reporting, too. Do you get an error code from SysUtils::File[Create|Open]() or ::CreateFile()?
  19. Remy Lebeau

    I keep being off by one

    Sounds like a corrupted build or environment. If you start a new project fresh, do you get the same problem? If so, you might try reinstalling the IDE.
  20. Remy Lebeau

    Reduce exe weight : Link with runtime package

    Because the VCL depends on the RTL. If you use the Runtime Package for the VCL then you need the Runtime Package of the RTL as well.
  21. Remy Lebeau

    I keep being off by one

    You can't put a breakpoint on a function declaration. Put the breakpoint inside of your main() function instead, at the spot where square() is actually being called: int main() { // ... square(nums, 10); // <-- breakpoint here!!! //... } Now you should be able to step into square() at runtime. Or, simply put the breakpoint inside of square() itself: void square(int *n, int num) { while(num) // <-- breakpoint here!!! { *n = *n * *n; num--; n++; } }
  22. Remy Lebeau

    Reduce exe weight : Link with runtime package

    Does your project use multiple build configurations (debug/release, 32bit/64bit, etc)? Do you have the runtime packages applied to every configuration?
  23. Remy Lebeau

    I keep being off by one

    Are you saying you get that when you put a breakpoint on the call to square() and then step into it? It should not be stepping into std code, let alone ntdll code. Are you sure you are not maybe stepping into the std::cout calls instead?
  24. Remy Lebeau

    I keep being off by one

    That makes no sense. You should show your paper logic. Entry into function: num=10 while (10) square 1 num=9 while (9) square 2 num=8 while (8) square 3 num=7 while (7) square 4 num=6 while (6) square 5 num=5 while (5) square 6 num=4 while (4) square 7 num=3 while (3) square 8 num=2 while (2) square 9 num=1 while (1) square 10 num=0 while (0) break 10 iterations total, and num is 0 after the last iteration. It can't be 1.
  25. Remy Lebeau

    I keep being off by one

    @357mag I don't understand what you are describing. Of course num reaches 0 or else the function would never exit. Proof: https://onlinegdb.com/bxMEvMyoc
×