I am a student in high school and I am currently learning in Delphi XE3. We are learning about BIT manipulation. We have an assignment and while I have read a lot on the subject and understand the entire process of storing information in Bits and SHL/SHR I am having difficulty understanding how to do this process in Delphi.
The assignment is as follows:
Decimal Hexidecimal Binary
1 0x0001 0000000000000001
2 0x0002 0000000000000010
4 0x0004 0000000000000100
Passing an integer value in an XML file to identify the options set. For example. If I wanted to send option 1 and option 2, I would add 1+2=3. I would send 3 as the number to specify that options 1 and 2 are true.
On the client the binary value would be 0000000000000011 = 3
From what I have read I need to use a mask but I do not understand how to do this. How would do I use masks in Delphi ot obtain the individual values which would be True or False.
I tried doing this in a regular Integer variable but it always gets treated as an Integer and the result is very strange. If I convert the integer to a binary string representation and I iterate thru the characters the result is correct but I am assuming that I should not be doing this with strings. Any help or an example would be greatly appreciated. Thank you.
You usually check if a particular bit is set in a Integer variable using the and binary operator, and you set individual bits using the or operator, like this:
const
OPTION_X = $01;
OPTION_Y = $02;
OPTION_Z = $04;
var
Options: Byte;
begin
Options := OPTION_X or OPTION_Y; //actually 3, like in your example
//check if option_X is set
if (Options and OPTION_X) = OPTION_X then
ShowMessage('Option X is set'); //this message is shown, because the bit is set
//check if option_Z is set
if (Options and OPTION_Z) = OPTION_Z then
ShowMessage('Option Z is set'); //this message is NOT shown
end;
The different OPTION_ constants, are actually masks, in the sense they are used to mask bits to zero (to check if a particular bit is set) or to mask bits to 1 (to set a particular bit).
Consider this fragment:
begin
..
if cbOptionX.Checked then
Options := Options or OPTION_X;
..
the or will mask the first bit to 1. If we start with a Options value (in binary) of 01010000, the resulting Options would be 01010001
01010000
OR 00000001 //OPTION_X
= 01010001
the same value is used to mask all the other bits to 0 to check if a particular bit is set. The if condition, for example: (Options and OPTION_Z) = OPTION_Z, does this:
first it MASKS all the non-interesting bytes of the Option variable to 0. If we consider the last value of 01010001, the operation will result in clearing all the bits, but the first.
01010001
AND 00000001
= 00000001
considering a starting value of 01010000 it will return zero:
01010000
AND 00000001
= 00000000
next, it compares if that value is equal to the mask itself. If it is equal, the bit was set in the original Options variable, otherwise it was not set. If your mask contains only one bit, that's matter of taste, you can just check if the resulting value is, for example, different than 0, but if your mask contains multiple bits and you want to check if all the bits was set, you have to check for equality.
Delphi has a predefined type TIntegerSet which allows to use set operators. Assuming that options is an Integer, you can check if any bit (0-based) is set like this:
option1 := 0 in TIntegerSet(options); { Bit 0 is set? }
option3 := 2 in TIntegerSet(options); { Bit 2 is set? }
Changing the options is done via Include or Exclude:
Include(TIntegerSet(options), 0); { set bit 0 }
Exclude(TIntegerSet(options), 2); { reset bit 2 }
Of course you can use any other set operator that may be helpful.
Delphi has Bitwise Operators for manipulating individual bits of integer types. Look at the shl, shr, and, or, and xor operators. To combine bits, use the or operator. To test for bits, use the and operator. For example, assuming these constants:
const
Option1 = 0x0001;
Option2 = 0x0002;
Option3 = 0x0004;
The or operator looks at the bits of both input values and produces an output value that has a 1 bit in places where either input value has a 1 bit. So combining bits would look like this:
var
Value: Integer;
begin
Value := Option1 or Option2;
{
00000000000000000000000000000001 Option1
00000000000000000000000000000010 Option2
-------------------------------- OR
00000000000000000000000000000011 Result
}
...
end;
The and operator looks at the bits of both input values and produces an output value that has a 1 bit only in places where both input value have a 1 bit, otherwise it produces a 0 bit instead. So testing for bits would look like this:
var
Value: Integer;
Option1Set: Boolean;
Option2Set: Boolean;
Option3Set: Boolean;
begin
Value := 7; // Option1 or Option2 or Option3
Option1Set := (Value and Option1) = Option1;
{
00000000000000000000000000000111 Value
00000000000000000000000000000001 Option1
-------------------------------- AND
00000000000000000000000000000001 Result
}
Option2Set := (Value and Option2) = Option2;
{
00000000000000000000000000000111 Value
00000000000000000000000000000010 Option2
-------------------------------- AND
00000000000000000000000000000010 Result
}
Option3Set := (Value and Option3) = Option3;
{
00000000000000000000000000000111 Value
00000000000000000000000000000100 Option3
-------------------------------- AND
00000000000000000000000000000100 Result
}
...
end;
Related
I am trying to get Unicode font glyph ranges (Delphi 6):
var GS:PGlyphSet;
GSSize:LongWord;
rng:TWCRange;
begin
GSSize := GetFontUnicodeRanges(Canvas.Handle, nil);
GetMem(Pointer(GS), GSSize);
try
GS.cbThis:=GSSize;
GS.flAccel:=0;
GS.cGlyphsSupported:=0;
GS.cRanges:=0;
if GetFontUnicodeRanges(Canvas.Handle, GS)<>0 then begin
for i:=0 to GS.cRanges-1 do begin
rng := GS.ranges[i];
The strange thing is that Length(GS.ranges) is 1, but GS.cRanges is 309 and when I try to access the second range GS.ranges[1] I get, of course, a range check error. Before I turned range checking on it has worked in some magical way.
Types for reference (from Windows module):
PWCRange = ^TWCRange;
{$EXTERNALSYM tagWCRANGE}
tagWCRANGE = packed record
wcLow: WCHAR;
cGlyphs: SHORT;
end;
TWCRange = tagWCRANGE;
PGlyphSet = ^TGlyphSet;
{$EXTERNALSYM tagGLYPHSET}
tagGLYPHSET = packed record
cbThis: DWORD;
flAccel: DWORD;
cGlyphsSupported: DWORD;
cRanges: DWORD;
ranges: array[0..0] of TWCRange;
end;
TGlyphSet = tagGLYPHSET;
This struct makes use of the so-called struct hack:
http://c-faq.com/struct/structhack.html
http://tonywearme.wordpress.com/2011/07/26/c-struct-hack/
The ranges member is a variable length array, placed inline in the struct. But you cannot actually encode that in a static C type. That's why you call the function to find out how much memory to allocate, and then heap allocate the struct. If you allocated it on the stack, or using SizeOf(...) then the struct would be too small.
The simplest thing to do is to disable range checking for the code that accesses ranges. Although the type declaration says that only 0 is a valid index for ranges, in fact 0..cRanges-1 are valid.
If you don't want to disable range checking for the relevant code, then take a pointer the element 0, and then use pointer arithmetic in your loop.
var
rng: PWCRange;
....
rng := #GS.ranges[0];
for i:=0 to GS.cRanges-1 do begin
// use rng^
inc(rng);
end;
This is, in my view, the cleanest way to write code for sequential access. For random access, and with range checking in force, you'd be compelled to declare some extra types to defeat range checking:
type
TWCRangeArray = array [0..(MaxInt div SizeOf(TWCRange))-1] of TWCRange;
PWCRangeArray = ^TWCRangeArray;
And then use type casting to access individual elements:
rng := PWCRangeArray(#GS.ranges)[i];
I'm tryin to scan an entire process memory but no success... What I'm doing is: for tests I'm using notepad, so I write there %B and this values in HEX are: 25(%) and 42(B). So the code is:
while (VirtualQueryEx(PIDHandle, Pointer(MemStart), MemInfo, SizeOf(MemInfo)) <> 0) do
begin
if ((MemInfo.State = MEM_COMMIT) and (not (MemInfo.Protect = PAGE_GUARD)
or (MemInfo.Protect = PAGE_NOACCESS)) and (MemInfo.Protect = PAGE_READWRITE)) then
begin
SetLength(Buff, MemInfo.RegionSize);
if (ReadProcessMemory(PIDHandle, MemInfo.BaseAddress, Buff,
MemInfo.RegionSize, ReceivedBytes)) then
begin
for I := 0 to SizeOf(Buff) do
begin
if (IntToHex(Buff[i], 1) = '25') and (IntToHex(Buff[i+2], 1) = '42') then
Form1.Memo1.Lines.Append(IntToHex(Buff[i], 1));
end;
end;
end;
MemStart:= MemStart + MemInfo.RegionSize;
end;
CloseHandle(PIDHandle);
end;
The var 'Buff' is TBytes (I read about TBytes and think it's same as array of byte). So I'm converting the bytes to Hex, and searching for values: 25 and 42 respectively. The code is like:
if (IntToHex(Buff[i], 1) = '25') and (IntToHex(Buff[i+2], 1) = '42') then
Because have 00 between the hex values. So I need to add '+2'. How can I scan the entire memory for this values??
Notepad uses Unicode so you'll need to look for UTF-16 encoded data, $0025 and $0042.
I don't understand why you feel the need to convert into hex strings before comparing. There's nothing special about hex that requires the use of strings. Hexadecimal is just a number system with base-16. So, decimal 32 is the same as hexadecimal 20, i.e. 32=$20. Do your comparison directly with integral values:
if (Buff[i]=$25) and (Buff[i+2]=$42) then
That said, taking into account the $00 bytes your test should really be something like this:
var
Target: string;
....
Target := '%B';
if CompareMem(#Buff[i], #Target[1], Length(Target)*SizeOf(Char)) then
....
I don't want to get too deep into the rest of your code, but this line
for I := 0 to SizeOf(Buff) do
is wrong on many different levels.
SizeOf(Buff) returns the size of a pointer since a dynamic array variable is essentially just a pointer. A useful thing to remember is that SizeOf is evaluated at compile time.
If you used Length instead of SizeOf then you would be iterating over the end of the list. To loop over a dynamic array, loop from 0 to Length(...)-1.
But in this case you are accessing index i+2 inside the loop, so you should loop from 0 to Length(...)-3.
But in fact you need to compare against 4 consecutive bytes to find a match. Perhaps like this:
TargetByteLength = Length(Target)*SizeOf(Char);
for i := 0 to Length(Buff)-TargetByteLength do
if CompareMem(#Buff[i], #Target[1], TargetByteLength) then
....
I've read a piece of Delphi code like this :
sample1 = ARRAY[1..80] OF INTEGER;
psample =^sample1;
VAR
function :ARRAY[1..70] OF psample;
From my understanding, the programmer is trying to declare an array that contains 70 pointers and each pointer points to a sample1 array.
So when I write :
function[1]^[1] := 5;
function[1]^[2] := 10;
then :
function[n]^[1] := 5
function[n]^[2] := 10; ( n = 2 to 70)
Is that correct ?
Your code sample is lacking some information since you do not say how function is defined. This means that you cannot draw the conclusions that you attempt to draw.
Of course, since function is a reserved word in Pascal, that code could never even compile. I will assume now that the variable is called f.
Consider the following definitions:
type
sample1 = array [1..80] of integer;
psample = ^sample1;
var
f : array [1..70] of psample;
Here, sample1 and psample are types. sample1 is type describing an array of 80 integers. psample is a pointer to a sample1.
Next a variable named f is defined. It is an array of 70 psamples.
Now, before you can even consider what happens when you write f[1]^[1], we need to assign some values to the elements of f.
Suppose we did it like this:
var
sample: sample1;
...
for i := 1 to 70 do
f[i] := #sample;
Now it would be true that f[i]^[k] refers to the same integer as f[j]^[k] for all valid i and j. So when you write f[1]^[1] := 42 you are also assigning that value to f[2]^[1], f[3]^[1] and so on.
On the other hand you could do it like this:
var
samples: array [1..70] of sample1;
...
for i := 1 to 70 do
f[i] := #samples[i];
Now each f[i] pointer points to a distinct array in memory. In this case assigning f[1]^[1] := 42 does not modify the value of f[2]^[1] or any of the other values.
That is correct. You have 70 pointers, each pointing to an array of 80 integers.
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.
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;
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.
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;
I have an integer field in a ClientDataSet and I need to compare to some values, something like this:
I can use const
const
mvValue1 = 1;
mvValue2 = 2;
if ClientDataSet_Field.AsInteger = mvValue1 then
or enums
TMyValues = (mvValue1 = 1, mvValue2 = 2);
if ClientDataSet_Field.AsInteger = Integer(mvValue1) then
or class const
TMyValue = class
const
Value1 = 1;
Value2 = 2;
end;
if ClientDataSet_Field.AsInteger = TMyValues.Value1 then
I like the class const approach but it seems that is not the delphi way, So I want to know what do you think
Declaration:
type
TMyValues = class
type TMyEnum = (myValue1, myValue2, myValue3, myValue4);
const MyStrVals: array [TMyEnum] of string =
('One', 'Two', 'Three', 'Four');
const MyIntVals: array [TMyEnum] of integer =
(1, 2, 3, 4);
end;
Usage:
if ClientDataSet_Field.AsInteger = TMyValues.MyIntVals[myValue1] then
A cast would generally be my last choice.
I wouldn't say that class consts are not the Delphi way. It's just they have been introduced to Delphi quite recently, and a lot of books and articles you'll find on the internet were written before their introduction, and thus you won't see them widely used. Many Delphi developers (I'd say the majority) will have started using Delphi before they were made available, and thus they're not the first thing that one thinks about.
One thing to consider is backwards compatibility - class constants are relatively new to Delphi so if your code has to be sharable with previous versions than they are out.
I typically use enumerated types, with the difference from yours is that my first enumeration is usually an 'undefined' item to represent NULL or 0 in an int field.
TmyValues = (myvUndefined, myvDescription1, myvDescription2)
if ClientDataSet_Field.AsInteger = Ord(myvDescription1) then...
To use a little bit of Jim McKeeth's answer - if you need to display to the user a text viewable version, or if you need to convert their selected text into the enumerated type, then an array comes in handy in conjuction with the type:
const MYVALS: array [TmyValues ] of string = ('', 'Description1', 'Description2');
You can then have utility functions to set/get the enumerated type to/from a string:
Function MyValString(const pMyVal:TmyValues):string;
begin
result := MYVALS[Ord(pMyVal)];
end;
Function StringToMyVal(const pMyVal:String):TMyValues;
var i:Integer;
begin
result := myvUndefined;
for i := Low(MYVALS) to High(MYVALS) do
begin
if SameText(pMyVal, MYVALS[i]) then
begin
result := TMyValues(i);
break;
end;
end;
end;
Continuing on... you can have scatter routine to set a combo/list box:
Procedure SetList(const DestList:TStrings);
begin
DestList.Clear;
for i := Low(MYVALS) to High(MYVALS) do
begin
DestList.Insert(MYVALS[i]);
end;
end;
In code: SetList(Combo1.Items) or SetList(ListBox1.Items)..
Then if you are seeing the pattern here... useful utility functions surrounding your enumeration, then you add everything to it's own class and put this class into it's own unit named MyValueEnumeration or whaterver. You end up with all the code surrounding this enumeration in one place and keep adding the utility functions as you need them. If you keep the unit clean - don't mix in other unrelated functionality then it will stay very handy for all projects related to that enumeration.
You'll see more patterns as time goes and you use the same functionality over and over again and you'll build a better mousetrap again.
When using constants I recommend assigning the type when the data type is a numeric float.
Delphi and other languages will not always evaluate values correctly if the types do not match...
TMyValue = class
const
// will not compare correctly to float values.
Value1 = 1; // true constant can be used to supply any data type value
Value2 = 2; // but should only be compared to similar data type
// will not compare correctly to a single or double.
Value3 = 3.3; // default is extended in debugger
// will not compare correctly to a single or extended.
Value1d : double = Value1; // 1.0
Value2d : double = Value2; // 2.0
end;
Compared float values in if () and while () statements should be compared to values of the same data type, so it is best to define a temporary or global variable of the float type used for any comparison statements (=<>).
When compared to the same float data type this format is more reliable for comparison operators in any programming language, not just in Delphi, but in any programming language where the defined float types vary from variable to constant.
Once you assign a type, Delphi will not allow you to use the variable to feed another constant, so true constants are good to feed any related data type, but not for comparison in loops and if statements, unless they are assigned and compared to integer values.
***Note: Casting a value from one float type to another may alter the stored value from what you entered for comparison purposes, so verify with a unit test that loops when doing this.
It is unfortunate that Delphi doesn't allow an enumeration format like...
TController : Integer = (NoController = 0, ncpod = 1, nextwave = 2);
or enforce the type name for access to the enumeration values.
or allow a class constant to be used as a parameter default in a call like...
function getControllerName( Controller : TController = TController.NoController) : string;
However, a more guarded approach that provides both types of access would be to place the enumeration inside a class.
TController = class
//const
//NoController : Integer = 1;
//ncpod : Integer = 2;
//nextwave : Integer = 3;
type
Option = (NoController = 0, ncpod = 1, nextwave = 2);
public
Class function Name( Controller : Option = NoController) : string; static;
end;
implementation
class function TController.Name( Controller : Option = NoController) : string;
begin
Result := 'CNC';
if (Controller = Option.nextwave) then
Result := Result + ' Piranha'
else if (Controller = Option.ncpod) then
Result := Result + ' Shark';
Result := Result + ' Control Panel';
end;
This approach will effectively isolate the values, provide the static approach and allow access to the values using a for () loop.
The access to the values from a floating function would be like this...
using TControllerUnit;
function getName( Controller : TController.Option = TController.Option.NoController) : string;
implementation
function getName( Controller : TController.Option = TController.Option.NoController) : string;
begin
Result := 'CNC';
if (Controller = TController.Option.nextwave) then
Result := Result + ' Piranha'
else if (Controller = TController.Option.ncpod) then
Result := Result + ' Shark';
Result := Result + ' Control Panel';
end;
so many options! :-) i prefer enums and routinely use them as you describe. one of the parts i like is that i can use them with a "for" loop. i do use class constants as well but prefer enums (even private enums) depending on what i'm trying to achieve.
TMyType=class
private const // d2007 & later i think
iMaxItems=1; // d2007 & later i think
private type // d2007 & later i think
TMyValues = (mvValue1 = 1, mvValue2 = 2); // d2007 & later i think
private
public
end;
An option you haven't thought of is to use a lookup table in the database and then you can check against the string in the database.
eg.
Select value, Description from tbl_values inner join tbl_lookup_values where tbl_values.Value = tbl_lookup_values.value
if ClientDataSet_Field.AsString = 'ValueIwant' then