Mike
Mike

Reputation: 29

Bitwise Comparison and Converting C to Delphi

I have the following C code:

pIBM [unsigned char *, a function parameter, for input]
pIEEE [unsigned char *, a function parameter, for output] 

char tmp[8];

memcpy(tmp, pIBM, 8);
memset(pIEEE, 0, 8);

if (*tmp && memcmp(tmp+1, pIEEE, 7) == 0)
{
   pIEEE[0] = pIEEE[1] = 0xff;
   pIEEE[2] = ~(*tmp);

   return;
}
  1. How does if (*tmp && memcmp(tmp+1, pIEEE, 7) == 0) work?
  2. How to convert the C code to Delphi, literal and/or otherwise?

Upvotes: 0

Views: 374

Answers (4)

Rudy Velthuis
Rudy Velthuis

Reputation: 28806

To 1:

if (*tmp && memcmp(tmp+1, pIEEE, 7) == 0)

is equivalent to (but not proper Delphi yet):

if (tmp^ <> 0) and (memcmp(tmp + 1, pIEEE, 7) = 0) then

Of course that is not proper Delphi (because arrays and pointers can not be treated the same way, in Delphi, and memcmp is not part of core Delphi), so try this:

if (tmp[0] <> 0) and CompareMem(@tmp[1], @pIEEE[0], 7) then

To 2:

var
  tmp: array[0..7] of Byte;
begin
  Move(pIBM[0], tmp[0], SizeOf(tmp));
  FillChar(pIEEE, 8, 0);
  if (tmp[0] <> 0) and CompareMem(@tmp[1], @pIEEE[0], 7) then
  begin
    pIEEE[0] := $FF;
    pIEEE[0] := $FF;
    pIEEE[2] := not tmp[0];
    Exit;
  end;
end;

That is more or less a "literal" translation. I guess you can see how it can be improved a little (by avoiding tmp and reading from pIBM directly).

Upvotes: 1

would be something as follows (sorry if my Pascal skills are a bit rusty) For Q1:

The condition if (*tmp && memcmp(tmp+1, pIEEE, 7) == 0) can be read as

if first char pointer by tmp (*tmp == tmp[0]) is not zero (!= '\0'), then compare the tmp array starting 2nd char with pIEEE array (up to seven chars), if that comparison is equal, then execute

pIEEE[0] = pIEEE[1] = 0xff;

pIEEE[2] = ~(*tmp);

As for Q2: Could be something like

pIBM [PChar, a function parameter, for input] pIEEE [PChar, a function parameter, for output]

var tmp, tmp2 : PChar;

var flag : SizeInt;

StrLCopy(tmp, pIBM, 8);

pIEEE[0] := #0;

pIEEE[1] := #0;

pIEEE[2] := #0;

pIEEE[3] := #0;

pIEEE[4] := #0;

pIEEE[5] := #0;

pIEEE[6] := #0;

pIEEE[7] := #0;

if ^tmp <> #0 then

begin

   Tmp2 := Tmp;

   Inc(Tmp2);

   Flag := StrLComp(Tmp2, pIEEE, 7);

   if Flag = 0 then

   begin

       pIEEE[0] = #ff;

       pIEEE[1] = #ff;

       pIEEE[2] = not tmp[0];

   end

end;

NOTE: PChar is the type equivalent to Null terminated strings in C, see the unit Strings.pas (or in FreePascal http://www.freepascal.org/docs-html/rtl/sysutils/pcharfunctions.html)

Upvotes: 0

alk
alk

Reputation: 70941

if (*tmp && memcmp(tmp+1, pIEEE, 7) == 0)

is the same as

if ((0 != tmp[0]) && (memcmp(&tmp[1], &pIEEE[0], 7) == 0))

So this is two tests:

  1. Doesn't tmp[0] contain \0'?
  2. Are the seven chars tmp[1] .. tmp[7] equal to the seven chars pEEE[0] .. pEEE[6]?

How to convert the C code to Delphi, literal and/or otherwise?

  1. Read the C code
  2. Understand what you read
  3. Write the corresponding Delphi code

Upvotes: 0

David Heffernan
David Heffernan

Reputation: 613003

if (*tmp && memcmp(tmp+1, pIEEE, 7) == 0)

Here tmp is an array that decays to a pointer. So *tmp is true when tmp[0] is not equal to zero. And the memcmp test returns true when the final 7 elements of the array match the contents of pIEEE. And pIEEE is initialized to contain zeros. I guess you know that && is the logical AND operator.

If I were writing this in Delphi it would look something like this:

type
  TMyData = array [0..7] of Byte;

function Foo(const IBM: TMyData): TMyData;
begin
  FillChar(Result, 8, 0);
  if (IBM[0]<>0) and CompareMem(@IBM[1], @Result[0], 7) then
  begin
    Result[0] := $ff;
    Result[1] := $ff;
    Result[2] := not IBM[0];
  end;
end;

Upvotes: 2

Related Questions