Remove bitmanip available in Phobos
This commit is contained in:
parent
db607f7602
commit
81b4fb88f5
@ -1,318 +0,0 @@
|
|||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bit manipulation.
|
|
||||||
*
|
|
||||||
* Copyright: Eugene Wissner 2018-2020.
|
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
|
||||||
* Mozilla Public License, v. 2.0).
|
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
|
||||||
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/bitmanip.d,
|
|
||||||
* tanya/bitmanip.d)
|
|
||||||
*/
|
|
||||||
module tanya.bitmanip;
|
|
||||||
|
|
||||||
import tanya.meta.metafunction;
|
|
||||||
import tanya.meta.trait;
|
|
||||||
import tanya.meta.transform;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether $(D_PARAM E) is a $(D_KEYWORD enum), whose members can be
|
|
||||||
* used as bit flags.
|
|
||||||
*
|
|
||||||
* This is the case if all members of $(D_PARAM E) are integral numbers that
|
|
||||||
* are either 0 or positive integral powers of 2.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* E = Some $(D_KEYWORD enum).
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM E) contains only bit flags,
|
|
||||||
* $(D_KEYWORD false) otherwise.
|
|
||||||
*/
|
|
||||||
template isBitFlagEnum(E)
|
|
||||||
{
|
|
||||||
enum bool isValid(OriginalType!E x) = x == 0
|
|
||||||
|| (x > 0 && ((x & (x - 1)) == 0));
|
|
||||||
static if (isIntegral!E)
|
|
||||||
{
|
|
||||||
enum bool isBitFlagEnum = allSatisfy!(isValid, EnumMembers!E);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
enum bool isBitFlagEnum = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
enum Valid
|
|
||||||
{
|
|
||||||
none = 0,
|
|
||||||
one = 1 << 0,
|
|
||||||
two = 1 << 1,
|
|
||||||
}
|
|
||||||
static assert(isBitFlagEnum!Valid);
|
|
||||||
|
|
||||||
enum Invalid
|
|
||||||
{
|
|
||||||
one,
|
|
||||||
two,
|
|
||||||
three,
|
|
||||||
four,
|
|
||||||
}
|
|
||||||
static assert(!isBitFlagEnum!Invalid);
|
|
||||||
|
|
||||||
enum Negative
|
|
||||||
{
|
|
||||||
one = -1,
|
|
||||||
two = -2,
|
|
||||||
}
|
|
||||||
static assert(!isBitFlagEnum!Negative);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates that $(D_PARAM field) contains only bits from $(D_PARAM E).
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* E = Some $(D_KEYWORD enum).
|
|
||||||
* field = Bit field.
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM field) is valid, $(D_KEYWORD false)
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
bool containsBitFlags(E)(E field)
|
|
||||||
if (isBitFlagEnum!E)
|
|
||||||
{
|
|
||||||
OriginalType!E fillField()
|
|
||||||
{
|
|
||||||
typeof(return) full;
|
|
||||||
static foreach (member; EnumMembers!E)
|
|
||||||
{
|
|
||||||
full |= member;
|
|
||||||
}
|
|
||||||
return full;
|
|
||||||
}
|
|
||||||
enum OriginalType!E full = fillField();
|
|
||||||
return (field & ~full) == OriginalType!E.init;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
enum E
|
|
||||||
{
|
|
||||||
one,
|
|
||||||
two,
|
|
||||||
three,
|
|
||||||
}
|
|
||||||
assert(containsBitFlags(E.one | E.two));
|
|
||||||
assert(!containsBitFlags(cast(E) 0x8));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows to use $(D_KEYWORD enum) values as a set of bit flags.
|
|
||||||
*
|
|
||||||
* $(D_PSYMBOL BitFlags) behaves the same as a bit field of type $(D_PARAM E),
|
|
||||||
* but does additional cheks to ensure that the bit field contains only valid
|
|
||||||
* values, this is only values from $(D_PARAM E).
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* E = Some $(D_KEYWORD enum).
|
|
||||||
*/
|
|
||||||
struct BitFlags(E)
|
|
||||||
if (isBitFlagEnum!E)
|
|
||||||
{
|
|
||||||
private OriginalType!E field;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs $(D_PSYMBOL BitFlags) from $(D_PARAM field).
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* field = Bits to be set.
|
|
||||||
*/
|
|
||||||
this(E field)
|
|
||||||
{
|
|
||||||
this.field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts $(D_PSYMBOL BitFlags) to a boolean.
|
|
||||||
*
|
|
||||||
* It is $(D_KEYWORD true) if any bit is set, $(D_KEYWORD false) otherwise.
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD true) if this $(D_PSYMBOL BitFlags) contains any
|
|
||||||
* set bits, $(D_KEYWORD false) otherwise.
|
|
||||||
*/
|
|
||||||
bool opCast(T : bool)()
|
|
||||||
{
|
|
||||||
return this.field != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts to the original type of $(D_PARAM E) ($(D_KEYWORD int) by
|
|
||||||
* default).
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD this) as $(D_INLINECODE OriginalType!T).
|
|
||||||
*/
|
|
||||||
OriginalType!E opCast(T : OriginalType!E)() const
|
|
||||||
{
|
|
||||||
return this.field;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests (&), sets (|) or toggles (^) bits.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* op = Operation.
|
|
||||||
* that = 0 or more bit flags.
|
|
||||||
*
|
|
||||||
* Returns: New $(D_PSYMBOL BitFlags) object.
|
|
||||||
*/
|
|
||||||
BitFlags opBinary(string op)(E that) const
|
|
||||||
if (op == "&" || op == "|" || op == "^")
|
|
||||||
{
|
|
||||||
BitFlags result = this;
|
|
||||||
mixin("return result " ~ op ~ "= that;");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
|
||||||
BitFlags opBinary(string op)(BitFlags that) const
|
|
||||||
if (op == "&" || op == "|" || op == "^")
|
|
||||||
{
|
|
||||||
BitFlags result = this;
|
|
||||||
mixin("return result " ~ op ~ "= that;");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
|
||||||
BitFlags opBinaryRight(string op)(E that) const
|
|
||||||
if (op == "&" || op == "|" || op == "^")
|
|
||||||
{
|
|
||||||
BitFlags result = this;
|
|
||||||
mixin("return result " ~ op ~ "= that;");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests (&), sets (|) or toggles (^) bits.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* op = Operation.
|
|
||||||
* that = 0 or more bit flags.
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD this).
|
|
||||||
*/
|
|
||||||
ref BitFlags opOpAssign(string op)(E that)
|
|
||||||
if (op == "&" || op == "|" || op == "^")
|
|
||||||
{
|
|
||||||
mixin("this.field " ~ op ~ "= that;");
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
|
||||||
ref BitFlags opOpAssign(string op)(BitFlags that)
|
|
||||||
if (op == "&" || op == "|" || op == "^")
|
|
||||||
{
|
|
||||||
mixin("this.field " ~ op ~ "= that.field;");
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inverts all bit flags.
|
|
||||||
*
|
|
||||||
* Returns: New $(D_PSYMBOL BitFlags) object with all bits inverted.
|
|
||||||
*/
|
|
||||||
BitFlags opUnary(string op : "~")() const
|
|
||||||
{
|
|
||||||
BitFlags result;
|
|
||||||
result.field = ~this.field;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assigns a bit field.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* that = Bit field of type $(D_PARAM E).
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD this).
|
|
||||||
*/
|
|
||||||
ref BitFlags opAssign(E that)
|
|
||||||
{
|
|
||||||
this.field = that;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares this $(D_PSYMBOL BitFlags) object to another bit field.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* that = $(D_PSYMBOL BitFlags) object or a bit field of type
|
|
||||||
* $(D_PARAM E).
|
|
||||||
*
|
|
||||||
* Returns: $(D_KEYWORD true) if $(D_KEYWORD this) and $(D_PARAM that)
|
|
||||||
* contain the same bits ,$(D_KEYWORD false) otherwise.
|
|
||||||
*/
|
|
||||||
bool opEquals(E that) const
|
|
||||||
{
|
|
||||||
return this.field == that;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
|
||||||
bool opEquals(BitFlags that) const
|
|
||||||
{
|
|
||||||
return this.field == that.field;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a hash value of this object.
|
|
||||||
*
|
|
||||||
* Returns: Hash value.
|
|
||||||
*/
|
|
||||||
size_t toHash() const
|
|
||||||
{
|
|
||||||
return cast(size_t) this.field;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a $(D_PSYMBOL BitFlags) object initialized with $(D_PARAM field).
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* E = Some $(D_KEYWORD enum).
|
|
||||||
* field = Bits to be set.
|
|
||||||
*/
|
|
||||||
BitFlags!E bitFlags(E)(E field)
|
|
||||||
if (isBitFlagEnum!E)
|
|
||||||
{
|
|
||||||
return BitFlags!E(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
enum E
|
|
||||||
{
|
|
||||||
one = 1 << 0,
|
|
||||||
two = 1 << 1,
|
|
||||||
three = 1 << 2,
|
|
||||||
}
|
|
||||||
// Construct with E.one and E.two set
|
|
||||||
auto flags = bitFlags(E.one | E.two);
|
|
||||||
|
|
||||||
// Test wheter E.one is set
|
|
||||||
assert(flags & E.one);
|
|
||||||
|
|
||||||
// Toggle E.one
|
|
||||||
flags ^= E.one;
|
|
||||||
assert(!(flags & E.one));
|
|
||||||
|
|
||||||
// Set E.three
|
|
||||||
flags |= E.three;
|
|
||||||
assert(flags & E.three);
|
|
||||||
|
|
||||||
// Clear E.three
|
|
||||||
flags &= ~E.three;
|
|
||||||
assert(!(flags & E.three));
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
module tanya.tests.bitmanip;
|
|
||||||
|
|
||||||
import tanya.bitmanip;
|
|
||||||
|
|
||||||
// Casts to a boolean
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
assert(BitFlags!One(One.one));
|
|
||||||
assert(!BitFlags!One());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assigns to and compares with a single value
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
BitFlags!One bitFlags;
|
|
||||||
bitFlags = One.one;
|
|
||||||
assert(bitFlags == One.one);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assigns to and compares with the same type
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
auto bitFlags1 = BitFlags!One(One.one);
|
|
||||||
BitFlags!One bitFlags2;
|
|
||||||
bitFlags2 = bitFlags1;
|
|
||||||
assert(bitFlags1 == bitFlags2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
assert((BitFlags!One() | One.one) == BitFlags!One(One.one));
|
|
||||||
assert((BitFlags!One() | BitFlags!One(One.one)) == BitFlags!One(One.one));
|
|
||||||
|
|
||||||
assert(!(BitFlags!One() & BitFlags!One(One.one)));
|
|
||||||
|
|
||||||
assert(!(BitFlags!One(One.one) ^ One.one));
|
|
||||||
assert(BitFlags!One() ^ BitFlags!One(One.one));
|
|
||||||
|
|
||||||
assert(~BitFlags!One());
|
|
||||||
|
|
||||||
assert(BitFlags!One().toHash() == 0);
|
|
||||||
assert(BitFlags!One(One.one).toHash() != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// opBinaryRight is allowed
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
static assert(is(typeof({ One.one | BitFlags!One(); })));
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum One : int
|
|
||||||
{
|
|
||||||
one = 1,
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user