diff options
Diffstat (limited to 'gcc/d/dmd/root/bitarray.d')
-rw-r--r-- | gcc/d/dmd/root/bitarray.d | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/gcc/d/dmd/root/bitarray.d b/gcc/d/dmd/root/bitarray.d new file mode 100644 index 00000000000..f9129611dd4 --- /dev/null +++ b/gcc/d/dmd/root/bitarray.d @@ -0,0 +1,192 @@ +/** + * Implementation of a bit array. + * + * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved + * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/bitarray.d, root/_bitarray.d) + * Documentation: https://dlang.org/phobos/dmd_root_array.html + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/bitarray.d + */ + +module dmd.root.bitarray; + +import core.stdc.stdio; +import core.stdc.string; + +import dmd.root.rmem; + +struct BitArray +{ + + alias Chunk_t = size_t; + enum ChunkSize = Chunk_t.sizeof; + enum BitsPerChunk = ChunkSize * 8; + + size_t length() const @nogc nothrow pure @safe + { + return len; + } + + void length(size_t nlen) nothrow pure + { + immutable ochunks = chunks(len); + immutable nchunks = chunks(nlen); + if (ochunks != nchunks) + { + ptr = cast(size_t*)mem.xrealloc_noscan(ptr, nchunks * ChunkSize); + } + if (nchunks > ochunks) + ptr[ochunks .. nchunks] = 0; + if (nlen & (BitsPerChunk - 1)) + ptr[nchunks - 1] &= (cast(Chunk_t)1 << (nlen & (BitsPerChunk - 1))) - 1; + len = nlen; + } + + void opAssign(const ref BitArray b) nothrow pure + { + if (!len) + length(b.len); + assert(len == b.len); + memcpy(ptr, b.ptr, bytes(len)); + } + + bool opIndex(size_t idx) const @nogc nothrow pure + { + import core.bitop : bt; + + assert(idx < len); + return !!bt(ptr, idx); + } + + void opIndexAssign(bool val, size_t idx) @nogc nothrow pure + { + import core.bitop : btc, bts; + + assert(idx < len); + if (val) + bts(ptr, idx); + else + btc(ptr, idx); + } + + bool opEquals(const ref BitArray b) const @nogc nothrow pure + { + return len == b.len && memcmp(ptr, b.ptr, bytes(len)) == 0; + } + + void zero() @nogc nothrow pure + { + memset(ptr, 0, bytes(len)); + } + + /****** + * Returns: + * true if no bits are set + */ + bool isZero() @nogc nothrow pure + { + const nchunks = chunks(len); + foreach (i; 0 .. nchunks) + { + if (ptr[i]) + return false; + } + return true; + } + + void or(const ref BitArray b) @nogc nothrow pure + { + assert(len == b.len); + const nchunks = chunks(len); + foreach (i; 0 .. nchunks) + ptr[i] |= b.ptr[i]; + } + + /* Swap contents of `this` with `b` + */ + void swap(ref BitArray b) @nogc nothrow pure + { + assert(len == b.len); + const nchunks = chunks(len); + foreach (i; 0 .. nchunks) + { + const chunk = ptr[i]; + ptr[i] = b.ptr[i]; + b.ptr[i] = chunk; + } + } + + ~this() nothrow pure + { + debug + { + // Stomp the allocated memory + const nchunks = chunks(len); + foreach (i; 0 .. nchunks) + { + ptr[i] = cast(Chunk_t)0xFEFEFEFE_FEFEFEFE; + } + } + mem.xfree(ptr); + debug + { + // Set to implausible values + len = cast(size_t)0xFEFEFEFE_FEFEFEFE; + ptr = cast(size_t*)cast(size_t)0xFEFEFEFE_FEFEFEFE; + } + } + +private: + size_t len; // length in bits + size_t *ptr; + + /// Returns: The amount of chunks used to store len bits + static size_t chunks(const size_t len) @nogc nothrow pure @safe + { + return (len + BitsPerChunk - 1) / BitsPerChunk; + } + + /// Returns: The amount of bytes used to store len bits + static size_t bytes(const size_t len) @nogc nothrow pure @safe + { + return chunks(len) * ChunkSize; + } +} + +nothrow pure unittest +{ + BitArray array; + array.length = 20; + assert(array[19] == 0); + array[10] = 1; + assert(array[10] == 1); + array[10] = 0; + assert(array[10] == 0); + assert(array.length == 20); + + BitArray a,b; + assert(a != array); + a.length = 200; + assert(a != array); + assert(a.isZero()); + a[100] = true; + b.length = 200; + b[100] = true; + assert(a == b); + + a.length = 300; + b.length = 300; + assert(a == b); + b[299] = true; + assert(a != b); + assert(!a.isZero()); + a.swap(b); + assert(a[299] == true); + assert(b[299] == false); + a = b; + assert(a == b); +} + + + |