DoxigAlpha

resize

Resizes to a new bit_length. If the new length is larger than the old length, fills any added bits with fill. If new_len is not zero, deinit must eventually be called.

Function parameters

Parameters

#
self:*@This()
new_len:usize
fill:bool

A bit set with runtime-known size, backed by an allocated slice

Types

#
DynamicBitSetUnmanaged
A bit set with runtime-known size, backed by an allocated slice
DynamicBitSet
A bit set with runtime-known size, backed by an allocated slice
IteratorOptions
Options for configuring an iterator over a bit set
Range
A range of indices within a bitset.

Returns the optimal static bit set type for the specified number

Functions

#
StaticBitSet
Returns the optimal static bit set type for the specified number
IntegerBitSet
A bit set with static size, which is backed by a single integer.
ArrayBitSet
A bit set with static size, which is backed by an array of usize.

Source

Implementation

#
pub fn resize(self: *@This(), allocator: Allocator, new_len: usize, fill: bool) !void {
    const old_len = self.bit_length;

    const old_masks = numMasks(old_len);
    const new_masks = numMasks(new_len);

    const old_allocation = (self.masks - 1)[0..(self.masks - 1)[0]];

    if (new_masks == 0) {
        assert(new_len == 0);
        allocator.free(old_allocation);
        self.masks = empty_masks_ptr;
        self.bit_length = 0;
        return;
    }

    if (old_allocation.len != new_masks + 1) realloc: {
        // If realloc fails, it may mean one of two things.
        // If we are growing, it means we are out of memory.
        // If we are shrinking, it means the allocator doesn't
        // want to move the allocation.  This means we need to
        // hold on to the extra 8 bytes required to be able to free
        // this allocation properly.
        const new_allocation = allocator.realloc(old_allocation, new_masks + 1) catch |err| {
            if (new_masks + 1 > old_allocation.len) return err;
            break :realloc;
        };

        new_allocation[0] = new_allocation.len;
        self.masks = new_allocation.ptr + 1;
    }

    // If we increased in size, we need to set any new bits
    // to the fill value.
    if (new_len > old_len) {
        // set the padding bits in the old last item to 1
        if (fill and old_masks > 0) {
            const old_padding_bits = old_masks * @bitSizeOf(MaskInt) - old_len;
            const old_mask = (~@as(MaskInt, 0)) >> @as(ShiftInt, @intCast(old_padding_bits));
            self.masks[old_masks - 1] |= ~old_mask;
        }

        // fill in any new masks
        if (new_masks > old_masks) {
            const fill_value = std.math.boolMask(MaskInt, fill);
            @memset(self.masks[old_masks..new_masks], fill_value);
        }
    }

    // Zero out the padding bits
    if (new_len > 0) {
        const padding_bits = new_masks * @bitSizeOf(MaskInt) - new_len;
        const last_item_mask = (~@as(MaskInt, 0)) >> @as(ShiftInt, @intCast(padding_bits));
        self.masks[new_masks - 1] &= last_item_mask;
    }

    // And finally, save the new length.
    self.bit_length = new_len;
}