views:

587

answers:

4

I want to create light object data-package to pass between client and server applications.

It is a so simple task, that I can control with only 1 byte, so each bit in a byte will have a different meaning,

Using only the bit

0 = False 
1 = True

Itens I need now:

1 - Loaded from database 
2 - Persisted
3 - Changed
4 - Marked to Delete
5 -
6 - 
7 - Null Value 
8 - Read Only


1) How do I use bit operators in Delphi to check each bit value? 
2) How do I set the bit Values?

Solution

After all help, Ill use the next Set

  TStateType = (
    stLoaded    = 0,   // loaded from persistance
    stNative    = 2,   // value loaded and converted to native type
    stPersisted = 3,   // saved
    stChanged   = 4,   // object or member changed
    stToDelete  = 5,   // marked to delete
    stReadOnly  = 6,   // read only object, will not allow changes
    stNull      = 7    // value is null
  );
  TState = Set of TStateType;

And for stream -> persistance, this will be the record to be used:

  TDataPackage = record
    Data: TBytes;
    TypeInfo: TMetaInfo;
    State: Byte;
    Instance: TBuffer;
  end;

Thank you guys, for all the answers and comments.

+1  A: 

This page describes Delphi operators, including bitwise operators.

It sounds like you need to use the and operator. For example:

const
  LOADED_FROM_DATABASE = 1;
  PERSISTED = 2;
  CHANGED = 4;
  // etc...

//...

if (bitFlags and LOADED_FROM_DATABASE) <> 0 then
begin
  // handle LOADED FROM DATABASE
end;

if (bitFlags and PERSISTED) <> 0 then
begin
  // handle PERSISTED
end;

// etc...

In order to set the flags, you can use OR:

bitFlags := LOADED_FROM_DATABASE or PERSISTED or CHANGED;
Scott W
@Scott, excellent. Thank you!
Cesar Romero
Sets are a better primitive for this in Delphi, as they are part of the syntax and semantics of the language, yet compile down to the same machine-code operations.
Barry Kelly
@Barry, thanks. Ill use Sets and cast to Byte when stream.
Cesar Romero
@Barry, I didn't even think of that, great idea!
Scott W
+6  A: 

I would use a set for this:

type
    TMyDatum = (mdLoaded, mdPersisted, mdChanged, mdMarkedToDelete, ...);
    TMyData = set of TMyDatum;

var
  Foo: TMyData;
begin 
  Foo := [mdLoaded, mdChanged];
  if (mdPersisted in Foo) then ...

These are implemented as integers, so you can pass them easily. And I find the code much, much more readable than bitwise operators.

Craig Stuntz
@Craig, this is what I have today. As I pointed in my question, it must be more light, and Im not sure about the size of a enumerated type. Also to stream 1 Byte, is more easy than stream Enumerated types. The code to test the bit values will be embedded inside a TStatus object, like Status.IsLoaded
Cesar Romero
Cesar - a set has a size of 1, 2, 3, 4 etc. bytes, however many necessary to fit in all the bits required, one bit per possible member of the set. Sets are directly equivalent to bitwise binary operations.
Barry Kelly
Cesar: It ain't broke, then. Don't "fix" it!
Craig Stuntz
@Barry, Thanks now I got how this really works, and learned I can cast to Byte.
Cesar Romero
@Craig, you are right, thanks.
Cesar Romero
+7  A: 

I'd really use a set for this. However, I see you really want a byte. Use sets everywhere then typecast to a byte in the end.

This solution will require much less typing, has support for standard delphi operators and really carries no performance penalty as Barry Kelly has pointed out.

procedure Test;
type
  TSetValues = (
    TSetValue1   = 0,
    TSetValue2   = 1,
    TSetValue4   = 2,
    TSetValue8   = 3,
    TSetValue16  = 4,
    TSetValue32  = 5,
    TSetValue64  = 6,
    TSetValue128 = 7
  );

  TMySet = set of TSetValues;
var
  myValue: byte;
  mySet: TMySet;
begin
  mySet := [TSetValue2, TSetValue16, TSetValue128];
  myValue := byte(mySet);
  ShowMessage(IntToStr(myValue)); // <-- shows 146
end;
PetriW
@PEtriW, Ill try this.
Cesar Romero
This is the winner, I think a little refactory will help me to improve my existing code.
Cesar Romero
A: 

I asked a related question here: "Is it faster to use an array or bit access for multiple boolean values? "

Tom A