As of now, everything except the code imported from FreeBSD is proprietary. Of course, it won't be like this for long, only until we have decided which license we like to use. The rationale is that releasing everything under a copyleft license later is always easier than doing so immediately and then changing it afterwards. Naturally, any changes made before this commit are still subject to the terms of the CNPL.
90 lines
2.3 KiB
C
90 lines
2.3 KiB
C
/* Copyright (C) 2021 fef <owo@fef.moe>. All rights reserved. */
|
|
|
|
#include <gay/bits.h>
|
|
#include <gay/types.h>
|
|
|
|
#include <limits.h>
|
|
|
|
void bit_set_range(unsigned long *bitfield, usize first, usize count)
|
|
{
|
|
/* skip ahead to the longword containing the first bit we need to set */
|
|
bitfield += first / LONG_BIT;
|
|
unsigned int bit = first % LONG_BIT;
|
|
|
|
/* test if the entire bit range is contained within this longword */
|
|
if (bit + count < LONG_BIT) {
|
|
unsigned long low_mask = (1lu << bit) - 1; /* 0b000..011 */
|
|
unsigned long high_mask = ~( (1lu << (bit + count)) - 1 ); /* 0b110..000 */
|
|
*bitfield |= ~(low_mask | high_mask);
|
|
} else {
|
|
/* if the first bit isn't longword aligned, manually set the upper
|
|
* bits in that longword, starting from the first bit's position */
|
|
if (bit != 0) {
|
|
unsigned long mask = (1lu << bit) - 1;
|
|
*bitfield++ |= ~mask;
|
|
count -= LONG_BIT - bit;
|
|
}
|
|
|
|
/* write out full longwords while we can */
|
|
while (count >= LONG_BIT) {
|
|
*bitfield++ = ~0lu;
|
|
count -= LONG_BIT;
|
|
}
|
|
|
|
/* set the remaining lower bits in the last longword, if any */
|
|
if (count != 0) {
|
|
unsigned long mask = (1lu << count) - 1;
|
|
*bitfield |= mask;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* this works the same way as bit_set_range, it's just the inverse */
|
|
void bit_clr_range(unsigned long *bitfield, usize first, usize count)
|
|
{
|
|
bitfield += first / LONG_BIT;
|
|
unsigned int bit = first % LONG_BIT;
|
|
|
|
if (bit + count < LONG_BIT) {
|
|
unsigned long low_mask = (1lu << bit) - 1;
|
|
unsigned long high_mask = ~( (1lu << (bit + count)) - 1 );
|
|
*bitfield &= low_mask | high_mask;
|
|
} else {
|
|
if (bit != 0) {
|
|
unsigned long mask = (1lu << bit) - 1;
|
|
*bitfield++ &= mask;
|
|
count -= LONG_BIT - bit;
|
|
}
|
|
|
|
while (count >= LONG_BIT) {
|
|
*bitfield++ = 0;
|
|
count -= LONG_BIT;
|
|
}
|
|
|
|
if (count != 0) {
|
|
unsigned long mask = (1lu << count) - 1;
|
|
*bitfield &= ~mask;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool bit_tst(const unsigned long *bitfield, usize pos)
|
|
{
|
|
usize index = pos / LONG_BIT;
|
|
unsigned long mask = 1 << (pos % LONG_BIT);
|
|
return (bitfield[index] & mask) != 0;
|
|
}
|
|
|
|
void bit_set(unsigned long *bitfield, usize pos)
|
|
{
|
|
usize index = pos / LONG_BIT;
|
|
unsigned long mask = 1 << (pos % LONG_BIT);
|
|
bitfield[index] |= mask;
|
|
}
|
|
|
|
void bit_clr(unsigned long *bitfield, usize pos)
|
|
{
|
|
usize index = pos / LONG_BIT;
|
|
unsigned long mask = 1 << (pos % LONG_BIT);
|
|
bitfield[index] &= ~mask;
|
|
}
|