The protocol declaration shows us that OptionSet inherits from the RawRepresentable protocol. This means the Schedule structure also needs to conform to the RawRepresentable protocol. This is easy enough, though. We declare a constant property, rawValue , of type Int. We've defined an option set, but how do we work with instances of the Schedule structure?
The Swift standard library comes to the rescue. For each option, we declare a static member. Notice that we use bitwise operators to define the raw value for each static member. Each static member has a unique value. Working with options sets is easy and intuitive.
Take a look at the example below in which we assign the static member wednesday to a variable. You can use an array to create an option set with one or more static members. It doesn't get easier than this. If you've worked with bitmasks in Objective-C, then I'm sure you agree Swift's implementation is easier to work with, less confusing, and more intuitive.
You can also use the initializer of the Schedule struct to create an option set. This is especially useful if you've stored the raw value in, for example, a database. Creating option sets is straightforward. But it doesn't stop here. The OptionSet protocol defines a collection of methods that make working with option sets easy and powerful. Take a look at the following example in which we combine two option sets. You can also define static members for convenience.
The example we've created in this tutorial makes it easy to work with schedules. We can define a few additional static members to make this even easier, more convenient. The weekend static member defines an option set that contains the values stored in. The weekdays static member only contains the days of the week.
More often, in practice, bits that are to be ignored are "masked off " or masked to 0 rather than "masked on " or masked to 1. There is no way to change a bit from on to off using the OR operation. Instead, bitwise AND is used. When a value is AND ed with a 1 , the result is simply the original value, as in: However, AND ing a value with 0 is guaranteed to return a 0 , so it is possible to turn a bit off by using AND with 0: To leave the other bits alone, use AND with 1.
Masking off the higher nibble bits 4, 5, 6, 7 the lower nibble bits 0, 1, 2, 3 unchanged. It is possible to use bitmasks to easily check the state of individual bits regardless of the other bits. To do this, turning off all the other bits using the bitwise AND is done as discussed above and the value is compared with 1.
If it is equal to 0 , then the bit was off, but if the value is any other value, then the bit was on. What makes this convenient is that it is not necessary to figure out what the value actually is, just that it is not 0. So far the article has covered how to turn bits on and turn bits off, but not both at once. Sometimes it does not really matter what the value is, but it must be made the opposite of what it currently is.
This can be achieved using the XOR exclusive or operation. XOR returns 1 if and only if an odd number of bits are 1. Therefore, if two corresponding bits are 1 , the result will be a 0 , but if only one of them is 1 , the result will be 1. Therefore inversion of the values of bits is done by XOR ing them with a 1. To write arbitrary 1s and 0s to a subset of bits, first write 0s to that subset, then set the high bits:.
In programming languages such as C , bit fields are a useful way to pass a set of named boolean arguments to a function. It can clear up to four buffers the color, depth, accumulation, and stencil buffers , so the API authors could have had it take four arguments.
But then a call to it would look like. Internally, a function taking a bitfield like this can use binary and to extract the individual bits. For example, an implementation of glClear might look like:. The advantage to this approach is that function argument overhead is decreased. Since the minimum datum size is one byte, separating the options into separate arguments would be wasting seven bits per argument and would occupy more stack space.
Instead, functions typically accept one or more bit integers, with up to 32 option bits in each. While elegant, in the simplest implementation this solution is not type-safe. To configure IP addresses on interfaces, masks start with and have the large values on the left side: This is sometimes called an inverse mask or a wildcard mask.
When the value of the mask is broken down into binary 0s and 1s , the results determine which address bits are to be considered in processing the traffic. A 0 indicates that the address bits must be considered exact match ; a 1 in the mask is a "don't care".