Question

I do not understand how flags work and would appreciate some help and a link to a tutorial to try and understand what is happening when adding values to an Integer as flags.

For example, I am backing up various-sized files to an SD card. A lot of the files often already exist, so I first run through and check FileExists, FileAge, and size, and if appropriate, add it to the list to copy across with ShFileOperation. Using a routine by Peter Barlow from here it is working but I want to suppress some things.

If the file is larger than 10M then I want to show the win-progress bar, I do not want a prompt for overwriting an existing file. Plus, I do not want it to check if there is enough room as I will have already done that so I know there is enough room for all the updates.

I have tried messing with AND and OR and + and - but can't seem to figure out the combination I need.

if aBigFile then
  OpStruc.fFlags:=FOF_NOCONFIRMATION or FOF_SIMPLEPROGRESS else
  OpStruc.fFlags:=FOF_SILENT or FOF_NOCONFIRMATION;

Could someone please give me an example of what I need to make this work?

Was it helpful?

Solution

And and or are bitwise operators. That means they apply to each bit of their operands independently. When learning about bitwise operations, it helps to picture the operands in binary rather than decimal. (Once you're familiar with how they work, decimal still isn't the ideal format; most people prefer hexadecimal instead, or, to a lesser extent, octal.)

For and, the result bit is set if and only if the bits of both operands are set; otherwise, the result is cleared. For or, the result is set if either one of the operand bits is set. It's also set when both are set, so it's known as inclusive or. (There's also exclusive or, where the result is set only when exactly one of the two operands is set. Delphi uses the xor operator for that.)

To compute a result for operands that are larger than one bit, the bits are computed in parallel, so the first bit of the result is computed from the first bits of the operands, the second bit from the second bits, and so on.

When combining flags, you use or to indicate that you want both flags set. For example:

// Indicate we want both a simple progress bar *and* a lack of confirmation.
OpStruc.fFlags := fof_NoConfirmation or fof_SimpleProgress;

The first flag's value in binary is 00010000. The second's is 000100000000. That makes the result 000100010000.

You won't frequently use and when setting flags. Rather, that's usually used when you want to check whether a flag is set. For example:

// Check whether the no-confirmation flag is set:
var FlagSet: Boolean;
FlagSet := (OpStruc.FFlags and fof_NoConfirmation) = fof_NoConfirmation;

Since the input was 000100010000, the result of the and with the flag value is 000000010000. That's equal to the flag value, so the value of FlagSet will be true.

It's sometimes enough to check whether the result of the and operation is non-zero, rather than to check that it's exactly equal to the flag you were testing. When the flag consists of multiple set bits, you want to check that all of them were present, though. If only one were present, the result of the and operation would still be non-zero.

To remove flags, you use not to invert the bits of the flag you want to remove (clearing all the set bits and vice versa), and then use and to clear those bits. For example:

OpStruc.FFlags := OpStruc.FFlags and not fof_SimpleProgress;

The inverse of fof_SimpleProgress is 111011111111. The value of FFlags so far is 000100010000. Combining those with and will yield 000000010000, which equals fof_NoConfirmation, just as we'd expect by removing fof_SimpleProgress.

Now that you understand how individual flag values get combined, you're equipped indicate which flags you want to pass to the particular API function you're having trouble with. Read the documentation for each flag and decide whether it's one you want to use. If it is, include it in your list of flags.

You can combine flags with or in any order. If you know you always want certain flags, and you conditionally want others, you can start with your list of common flags and then add others later. For example:

OpStruc.FFlags := fof_NoConfirmation or fof_SimpleProgress;
if BigFiles then
  OpStruct.FFlags := OpStruc.FFlags or fof_Silent;

It will frequently work to use addition to combine flags. Obviously, the result of fof_NoConfirmation or fof_SimpleProgress is equal to fof_NoConfirmation + fof_SimpleProgress. However, that only works when the bit values of each flag are distinct, and when no flag is included more than once. The result of fof_Silent or fof_Silent is equal to fof_Silent, whereas the result of fof_Silent + fof_Silent is fof_RenameOnCollision, which is an entirely unrelated flag. Always use and and or when working with flags, never + and -.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top