Solved

Porting a packed variant record with bit fields

Posted on 2006-11-09
5
683 Views
Last Modified: 2010-04-05
We've got a program to port which heavily uses a record with variant parts looking something like this:
 TData = packed record
    case integer of
      1: (sword : word);
      2: (byte0 : byte; byte1: byte);
      3: (bits10_0 : 0..1023; bits 6_10 : 0..63);
    etc.

In other words, the record is supposed to store a single word, but there are different methods of accessing that word - or parts of that word. Delphi creates this record as a word for each entry (SizeOf returns 16). Setting mydata.sword to $1234 and then reading mydata.byte0 returns 0 instead of $34.

My immediate reaction was to create a class with properties called bits10_0 and Getbits10_0 and Setbits10_0 as that would involve the minimum of changes. But, of course, classes are not variables like records are.

The only thing I can think of is to change every single read and write of these data items with a function or procedure instead. There are potentially 1000 of these - and a find/replace won't work. Is there a better and easier solution?

Thanks
0
Comment
Question by:gmayo
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 
LVL 17

Accepted Solution

by:
Wim ten Brink earned 125 total points
ID: 17905341
If it's supposed to store a single word, it SizeOf would return the size of a word, thus 2 bytes. You're having 16 bytes here...

The solution would be to use operators like AND/OR/XOR and SHL/SHR on this. For example,
if you want to get the right-most 3 bits, use: MyData and $0007
If you want the 4 bits to the left, use: (MyData AND $F000) SHR 12
if you want to set the 8 bytes in the middle, use: MyData := MyData or ((Value SHL 4) and $0FF)

Yeah, I know... C++ does this easier since C++ allows you to manipulate data at the bit-level. Delphi only supports the byte level.

Btw, this part: (bits10_0 : 0..1023; bits 6_10 : 0..63);
That will already make your record 3 bytes in size. First two bytes for the range 0..1023 and then one byte for the range 0..63. So your overhead comes from this construction.

In Delphi 2006 it is possible to write record methods so that would allow you to do something like this:

type
  TData = packed record
    Data: Word;
    function GetBits10_0: Word;
    procedure SetBits10_0(Value: Word);
    property Bits10_0: Word read GetBits10_0 write SetBits10_0;
  end;

And of course you would have to write code that will AND/OR/XOR/SHL/SHR the data in it's proper place. And it's still just a record so no inheritance here. Or overriding methods. Or virtual methods. The SizeOf would just return 2 in this case.
0
 
LVL 8

Author Comment

by:gmayo
ID: 17905386
(bits10_0 : 0..1023; bits 6_10 : 0..63); is actually 16 bits, ie 2 bytes.

The reason Delphi reports 16 bytes insteaf of 2 is because there is another Case with 16 "bits" which Delphi treats as bytes, hence 16 bytes. It will always return the *largest* possible size of the variant record.

I know how I can solve this by changing all the access routines that do the bit manipulation, but as I say, there are around 1000 of them and I don't want to change each one by hand. Obviously these would involve and/or/shl/shr etc.

Interesting that D2006 supports methods in records. I have a copy of that somewhere.

The annoying thing is, I did exactly the same thing about 10 years ago - but I can't remember how I solved it then!

Thanks.
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 17905509
As an alternative option, you might want to use a set.

type
  TData = packed record
    case integer of
      1: (Data: Word);
      2: (Byte1, Byte2: Byte);
      3: (DataSet: set of 0..15);
    end;

This is exactly two bytes and allows you to manipulate every bit and also the whole package. And the lower and higher byte. And of course you could use set operators to check and modify the contents. (For example, multiplying or adding two sets...)
0
 
LVL 9

Expert Comment

by:alkisg
ID: 17917452
Put properties in your struct. I tried this in Delphi 2006 and worked fine:

type
  TenBits = 0..1023;
  TData = packed record
    function GetBits0_9: TenBits;
    procedure SetBits0_9(value: TenBits);
    property Bits0_9: TenBits read GetBits0_9 write SetBits0_9;
    case byte of
      1: (sword : word);
      2: (byte0 : byte; byte1: byte);
    end;

function TData.GetBits0_9: TenBits;
begin
  Result := sword and $3FF;
end;

procedure TData.SetBits0_9(value: TenBits);
begin
  sword := sword and $FC00 or value;
end;
0
 
LVL 8

Author Comment

by:gmayo
ID: 18043792
The Delphi2006 option seems easiest - thanks.

Geoff M.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
Suggested Courses
Course of the Month5 days, 15 hours left to enroll

626 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question