3

This is my first time installing the libraries for Lockbox. I downloaded version 3.4.3 from sourceforge and have Delphi 7. The first step is to get this sucker to compile under Delphi 7 and it's been hell. I do hope that the components are easier to use once installed.

Ok. I have a unit that looks like this.

unit uTPLb_StrUtils;

interface

uses
  SysUtils, uTPLb_D7Compatibility;

function AnsiBytesOf(const S: string): TBytes;

implementation

function AnsiBytesOf(const S: string): TBytes;
begin
//compiler chokes here
  **Result := TEncoding.ANSI.GetBytes(S);**
end;

end.

BTW, the compatibility unit defines TBytes as TBytes = packed array of byte;

Delphi 7 chokes on the TEncoding because it only exists in D2009+. What do I replace this function with?

Debbie
  • 125
  • 1
  • 1
  • 6

3 Answers3

5

String is an 8bit AnsiString in Delphi 7. Simply allocate the TBytes to the Length() of the string and Move() the string content into it:

function AnsiBytesOf(const S: AnsiString): TBytes;
begin
  SetLength(Result, Length(S) * SizeOf(AnsiChar));
  Move(PChar(S)^, PByte(Result)^, Length(Result));
end;

If you want to be politically correct and match what TEncoding.GetBytes() does, you would have to convert the String to a WideString and then use the Win32 API WideCharToMultiBytes() function to convert that to bytes:

function AnsiBytesOf(const S: WideString): TBytes;
var
  Len: Integer;
begin
  Result := nil;
  if S = '' then Exit;
  Len := WideCharToMultiByte(0, 0, PWideChar(S), Length(S), nil, 0, nil, nil);
  if Len = 0 then RaiseLastOSError;
  SetLength(Result, Len+1);
  WideCharToMultiByte(0, 0, PWideChar(S), Length(S), PAnsiChar(PByte(Result)), Len, nil, nil);
  Result[Len] = $0;
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0
function Quux(const S: AnsiString): TBytes;
var
  Count: Integer;
begin
  Count := Length(S) * SizeOf(AnsiChar);
  {$IFOPT R+}
  if Count = 0 then Exit; // nothing to do
  {$ENDIF}
  SetLength(Result, Count);
  Move(S[1], Result[Low(Result)], Count);
end;
Free Consulting
  • 4,300
  • 1
  • 29
  • 50
  • 2
    If the `AnsiString` is empty, accessing `S[1]` will crash with a bounds error. – Remy Lebeau Sep 23 '14 at 16:58
  • @RemyLebeau, just tested with my XE2 and it doesn't, hmm. – Free Consulting Sep 23 '14 at 17:03
  • On my XE2, accessing `S[1]` of a blank `AnsiString` raises an `ERangeError` if range checks are enabled, otherwise it raises an `EAccessViolation` when reading from address $00000000 (which makes sense as a blank string is a `nil` pointer). – Remy Lebeau Sep 23 '14 at 17:38
  • @RemyLebeau, while range check error (if enabled) makes perfect sense, access violation doesn't, because there is no access to `nil^` when `Count` is zero. – Free Consulting Sep 23 '14 at 18:20
  • 1
    You are right, the AV only occurs if the memory is actually read from. I wasn't using `Move()` when I did my `S[1]` test. Still, `Quux()` should handle the case of `Count=0` so it can avoid an `ERangeCheck` error when range checking is enabled. – Remy Lebeau Sep 23 '14 at 18:30
  • The clean way, as I have belatedly learnt from others here, is `Move(Pointer(...), ..., Count)` as shown by Remy. I used Pointer rather than PxxxChar cast because there's no need to ensure null terminator. – David Heffernan Sep 23 '14 at 19:36
  • @DavidHeffernan, what are advantages of not referencing first char of `string`? – Free Consulting Sep 23 '14 at 19:46
  • You can keep the code cleaner and simpler. A two liner using two Pointer casts. No range checking to deal with. Revert to your first revision and the second line is: `Move(Pointer(S)^, Pointer(Result)^, Count)` – David Heffernan Sep 23 '14 at 19:47
  • @DavidHeffernan, yeah, I use `Pointer` cast sometimes. But here I was emphasising a conversion between 1-based and 0-based arrays, otherwise equivalent in memory. Also, an interesting trait of `S[1]` is what it readily compatible with `ShortString` as well. – Free Consulting Sep 23 '14 at 20:04
0

You can get LB 3.5 here:

http://lockbox.seanbdurkin.id.au/Grok+TurboPower+LockBox

Try 3.5 instead.

Sean B. Durkin
  • 12,659
  • 1
  • 36
  • 65