Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 11/27/20 in Posts

  1. Rule #1 - Don't do shit before your application has loaded and displayed itself. After the initial display, you can show various "Preparing good stuff - % complete" messages and do stuff in threads, allowing basic interaction with the app - such as doing an immediate exit. Speed is mostly about perception.
  2. Mahdi Safsafi

    Hex2Binary

    @Stefan Glienke You're unbelievable man ! The next time I'm going to demonstrate something ... I'll make sure that Stefan will not find a link between the input and the output (hmm TRNGs)
  3. Oh so 20's: Today, I say "Alexa, kill bill" Next year, I think: "GPT-3, optimize Windows and solve my customer Scott's code issues"
  4. FPiette

    Byte Array to String

    RTFBody is an array of byte, each byte is an ASCII character, the last one being #0. You can consider this as being a C string type. To save it to a file, you can write: procedure TForm1.Button1Click(Sender: TObject); var ANameSpace : Variant; AFolderItem : Variant; AMailItem : Variant; RTFBody : array of Byte; Stream : TFileStream; begin OutlookApplication1.Connect; ANameSpace := OutlookApplication1.GetNameSpace('MAPI'); AFolderItem := ANameSpace.GetDefaultFolder(olFolderInbox); AMailItem := AFolderItem.Items(1); RTFBody := AMailItem.RTFBody; Stream := TFileStream.Create('RTFBody.rtf', fmCreate); try Stream.Write(RTFBody[0], Length(RTFBody)); finally Stream.Free; end; end; If you want to convert to a string here is a possibility: Get it into an AnsiString using SetString. Convert the AnsiString to String (Unicode). Now you can handle it as any other string. Here is some example code to display the first email body in a TMemo: procedure TForm1.Button1Click(Sender: TObject); var ANameSpace : Variant; AFolderItem : Variant; AMailItem : Variant; RTFBody : array of Byte; RTFAnsiString : AnsiString; RTFString : String; begin OutlookApplication1.Connect; ANameSpace := OutlookApplication1.GetNameSpace('MAPI'); AFolderItem := ANameSpace.GetDefaultFolder(olFolderInbox); AMailItem := AFolderItem.Items(1); RTFBody := AMailItem.RTFBody; SetString(RTFAnsiString, PAnsiChar(@RTFBody[0]), Length(RTFBody)); RTFString := String(RTFAnsiString); Memo1.Lines.Add(RtfString); end; Don't forget to add error checking in the code (No Outlook, no mail, empty mail,...).
  5. Since your concern is about startup time, there's a very handy way to find the culprit: Comment your code. All the objects( data modules, forms, classes ) created before the "application.run" should be checked for "legacy code not required anymore" If your project starts creating only the main form, then check the constructor and show form. And don't be shy! comment everything! even assignments (you never know what a setter might be doing) You will find out some leftovers from the past, that made perfect sense last decade, that are no longer required. The library you are using are among the best in delphi ecosystem, but... since you mention IBObjects, and FireDac, are you sure there's no query being executed at startup? DB Stuff might usually be rather slow, specially if some event's are alive during startup!
  6. David Heffernan

    Byte Array to String

    If it's a byte array, why don't you just write that to file? Why do you need to convert it to a string variable?
  7. Why? Because not seeing the application work is easy to confuse with seeing the application not working.
  8. Anders Melander

    Drag an Drop

    Well, you shouldn't really be solving that by giving the application full access to everything - but that's a different issue.
  9. microtronx

    HTML Library review and sale: 25% off.

    Very stable and good components + very good support. We can recommend htmlcomponents fully! Thanks for your work Alexander!
  10. Alexander Sviridenkov

    HTML Library review and sale: 25% off.

    @dummzeuch full source code is included for all licenses / products. Also it includes one year of support and all updates (major/minor).
  11. SamplingProfiler usually gives a good overview to find the particularly time consuming parts. (although it says up to XE4 on that page it works just fine for up to 10.4)
  12. As a guideline: try to remove overhead from prologues and epilogues caused by variables of managed types (explicit or implicit) such as strings or interfaces that are only there for the uncommon path. Another example was the error raising code in the hextobin thread that can be put into a subroutine that gets called only when the rase case of a invalid char occurs. Eric Grange wrote a nice article about this some years ago that I like to recommend: https://www.delphitools.info/2009/05/06/code-optimization-go-for-the-jugular/
  13. Mahdi Safsafi

    Hex2Binary

    @David Heffernan Few remarks about your code if you don't mind : 1- Its pointless to use string when characters are fixed in size ... Simply use static array of X char. 2- Its also pointless to calculate index when you already used a case ... Simply declare your array using char-range. In your case, compiler generated additional instructions to compute the index. function HexToBin2(const HexValue: string): string; type TChar4 = array [0 .. 3] of Char; PChar4 = ^TChar4; const Table1: array ['0' .. '9'] of TChar4 = ('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001'); Table2: array ['a' .. 'f'] of TChar4 = ('1010', '1011', '1100', '1101', '1110', '1111'); var HexDigit: Char; P: PChar4; begin SetLength(Result, Length(HexValue) * 4); P := PChar4(Result); for HexDigit in HexValue do begin case HexDigit of '0' .. '9': P^ := Table1[HexDigit]; 'a' .. 'f': P^ := Table2[HexDigit]; 'A' .. 'F': P^ := Table2[Chr(Ord(HexDigit) xor $20)]; else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexDigit, HexValue]); end; Inc(P); end; end;
  14. David Heffernan

    Hex2Binary

    I'd probably write it something like this: function HexToBin(const HexValue: string): string; const BinaryValues: array [0..15] of string = ( '0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111' ); var HexDigit: Char; HexDigitValue: Integer; Ptr: PChar; begin SetLength(Result, Length(HexValue) * 4); Ptr := Pointer(Result); for HexDigit in HexValue do begin case HexDigit of '0'..'9': HexDigitValue := Ord(HexDigit) - Ord('0'); 'a'..'f': HexDigitValue := 10 + Ord(HexDigit) - Ord('a'); 'A'..'F': HexDigitValue := 10 + Ord(HexDigit) - Ord('A'); else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexDigit, HexValue]); end; Move(Pointer(BinaryValues[HexDigitValue])^, Ptr^, 4 * SizeOf(Char)); Inc(Ptr, 4); end; end; Some notes: A case statement makes this quite readable in my view. You really don't want to be wasting time using Pos to search within a string. You can get the value directly with arithmetic. I prefer to perform just a single allocation, rather than use repeated allocations with concatenation. You might want to consider how to treat leading zeros. For instance how should you treat 0F, should that be 00001111 or 1111? I'd expect that both would be desirable in different situations, so an option in an extra argument to the function would be needed.
×