Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2013-04

Why does this work?

4 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Reinier Olislagers

As a certified high-level coder with a fear for anything that smells like pointers and bits I hesitated to post this as the answer may well be: figure it out yourself, it's obvious ;)... but at least it's worth a laugh to you bitpushers out there.

Have mercy ;)

Going through the dbase code, I hit this code:
(TDbfFile.UpdateNullField in db_dbffile)

src, dst: pointers (to buffers).

FNullField is a field that has a bitmap of flags for setting a field to NULL: bit 0=first field, bit 1=second field etc.
Those bits are stored beginning in FNullField.Offset; it can span multiple bytes (apparently stored BE: the first field goes into the lower byte, the 8th field in the next byte).

I have a lot of trouble with shr and shl going on. The first line seemingly drops the three lower bits... but why?
... and some bits are shifted back again in the next line? Arggh!

  if (FNullField  nil) and (Dst = nil) and (AFieldDef.NullPosition >=
0) then
  begin
    Src := PChar(Src) + FNullField.Offset + (AFieldDef.NullPosition shr 3);
    Result := (PByte(Src)^ and (1 shl (AFieldDef.NullPosition and $7))) = 0;
    exit;
  end;

Any suggestions?

Thanks,
Reinier

Reply by email

Marco van de Voort
to Reinier Olislagers

In our previous episode, Reinier Olislagers said:

Show quoted text 7 lines
multiple bytes (apparently stored BE: the first field goes into the lower byte, the 8th field in the next byte). I have a lot of trouble with shr and shl going on. The first line seemingly drops the three lower bits... but why? ... and some bits are shifted back again in the next line? Arggh!

No, the second takes the remaining 3 bits ( and $7), which is the bit number inside the byte, and does (1 shl that value) which is like 2 to the power that value. IOW it changes a bit index to a bit mask.

So the first line calculates the position of a byte from a bit index. The second takes the remainining bits of the index inside the byte and tests it. The function returns true if it is false (=0) btw.

Src := PChar(Src) + FNullField.Offset + (AFieldDef.NullPosition shr 3); Result := (PByte(Src)^ and (1 shl (AFieldDef.NullPosition and $7))) = 0;

Reply by email

Ludo Brands
to Reinier Olislagers: As a certified high-level coder with a fear for anything that smells like pointers and…
Reinier Olislagers wrote 8 lines
if (FNullField nil) and (Dst = nil) and (AFieldDef.NullPosition >= 0) then begin Src := PChar(Src) + FNullField.Offset + (AFieldDef.NullPosition shr 3); Result := (PByte(Src)^ and (1 shl (AFieldDef.NullPosition and $7))) = 0; exit; end;

NullPosition is a bit position, 8 bits in a byte. To find bit x you have to look in byte Start + x div 8. x div 8 can be written as x shr 3. Now that you have found the byte where bit x is you need to isolate that bit. Its position in the byte is X mod 8 which you can write as X and $7. The 1 shl (X and $7) is done to create a mask to get the correct bit.

Ludo

Reply by email

Reinier Olislagers
to Ludo Brands
Ludo Brands wrote 17 lines
On 04/12/2013 11:47 AM, Reinier Olislagers wrote: > if (FNullField nil) and (Dst = nil) and (AFieldDef.NullPosition >= > 0) then > begin > Src := PChar(Src) + FNullField.Offset + (AFieldDef.NullPosition shr 3); > Result := (PByte(Src)^ and (1 shl (AFieldDef.NullPosition and $7))) = 0; > exit; > end; > NullPosition is a bit position, 8 bits in a byte. To find bit x you have to look in byte Start + x div 8. x div 8 can be written as x shr 3. Now that you have found the byte where bit x is you need to isolate that bit. Its position in the byte is X mod 8 which you can write as X and $7. The 1 shl (X and $7) is done to create a mask to get the correct bit. Ludo

Thanks Marco & Ludo,

The penny finally dropped.

Regards,
Reinier

Reply by email