blob: af90a9c7271c13bbd3db3bf0ffd29e3f87868357 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <bitmap/bitmap.h>
#include <stddef.h>
#include <zircon/types.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/macros.h>
#ifdef _KERNEL
#include <ktl/unique_ptr.h>
#else
#include <fbl/unique_ptr.h>
#endif
namespace bitmap {
struct RleBitmapElement;
#ifdef _KERNEL
using RleBitmapElementPtr = ktl::unique_ptr<RleBitmapElement>;
#else
using RleBitmapElementPtr = fbl::unique_ptr<RleBitmapElement>;
#endif
// A run-length encoded bitmap.
class RleBitmap final : public Bitmap {
private:
// Private forward-declaration to share the type between the iterator type
// and the internal list.
using ListType = fbl::DoublyLinkedList<RleBitmapElementPtr>;
public:
using const_iterator = ListType::const_iterator;
using FreeList = ListType;
constexpr RleBitmap()
: num_elems_(0), num_bits_(0) {}
virtual ~RleBitmap() = default;
RleBitmap(RleBitmap&& rhs) = default;
RleBitmap& operator=(RleBitmap&& rhs) = default;
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(RleBitmap);
// Returns the current number of ranges.
size_t num_ranges() const { return num_elems_; }
// Returns the current number of bits.
size_t num_bits() const { return num_bits_; }
zx_status_t Find(bool is_set, size_t bitoff, size_t bitmax,
size_t run_len, size_t* out) const override;
// Returns true if all the bits in [*bitoff*, *bitmax*) are set. Afterwards,
// *first_unset* will be set to the lesser of bitmax and the index of the
// first unset bit after *bitoff*.
bool Get(size_t bitoff, size_t bitmax, size_t* first_unset = nullptr) const override;
// Sets all bits in the range [*bitoff*, *bitmax*). Only fails on allocation
// error or if bitmax < bitoff.
zx_status_t Set(size_t bitoff, size_t bitmax) override;
// Sets all bits in the range [*bitoff*, *bitmax*). Only fails if
// *bitmax* < *bitoff* or if an allocation is needed and *free_list*
// does not contain one.
//
// *free_list* is a list of usable allocations. If an allocation is needed,
// it will be drawn from it. This function is guaranteed to need at most
// one allocation. If any nodes need to be deleted, they will be appended
// to *free_list*.
zx_status_t SetNoAlloc(size_t bitoff, size_t bitmax, FreeList* free_list);
// Clears all bits in the range [*bitoff*, *bitmax*). Only fails on allocation
// error or if bitmax < bitoff.
zx_status_t Clear(size_t bitoff, size_t bitmax) override;
// Clear all bits in the range [*bitoff*, *bitmax*). Only fails if
// *bitmax* < *bitoff* or if an allocation is needed and *free_list*
// does not contain one.
//
// *free_list* is a list of usable allocations. If an allocation is needed,
// it will be drawn from it. This function is guaranteed to need at most
// one allocation. If any nodes need to be deleted, they will be appended
// to *free_list*.
zx_status_t ClearNoAlloc(size_t bitoff, size_t bitmax, FreeList* free_list);
// Clear all bits in the bitmap.
void ClearAll() override;
// Iterate over the ranges in the bitmap. Modifying the list while
// iterating over it may yield undefined results.
const_iterator cbegin() const { return elems_.cbegin(); }
const_iterator begin() const { return elems_.cbegin(); }
const_iterator end() const { return elems_.cend(); }
const_iterator cend() const { return elems_.cend(); }
private:
zx_status_t SetInternal(size_t bitoff, size_t bitmax, FreeList* free_list);
zx_status_t ClearInternal(size_t bitoff, size_t bitmax, FreeList* free_list);
// The ranges of the bitmap. Ranges are ordered by ascending |bitoff| value.
// When no "Set" operation is in progress, there should not be any overlapping ranges.
ListType elems_;
// The number of ranges in elems_.
size_t num_elems_;
// The number of total bits in elems_; i.e. the sum of the bitlen field of all stored
// RleBitmapElements.
size_t num_bits_;
};
// Elements of the bitmap list
struct RleBitmapElement : public fbl::DoublyLinkedListable<RleBitmapElementPtr> {
// The start of this run of 1-bits.
size_t bitoff;
// The number of 1-bits in this run.
size_t bitlen;
// The (inclusive) start of this run of 1-bits.
size_t start() const { return bitoff; }
// The (exclusive) end of this run of 1-bits.
size_t end() const { return bitoff + bitlen; }
};
} // namespace bitmap