summaryrefslogtreecommitdiffstats
path: root/js/src/zydis/Zycore/Bitset.c
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/zydis/Zycore/Bitset.c')
-rw-r--r--js/src/zydis/Zycore/Bitset.c670
1 files changed, 670 insertions, 0 deletions
diff --git a/js/src/zydis/Zycore/Bitset.c b/js/src/zydis/Zycore/Bitset.c
new file mode 100644
index 0000000000..527ea37739
--- /dev/null
+++ b/js/src/zydis/Zycore/Bitset.c
@@ -0,0 +1,670 @@
+/***************************************************************************************************
+
+ Zyan Core Library (Zycore-C)
+
+ Original Author : Florian Bernd
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+
+***************************************************************************************************/
+
+#include "zydis/Zycore/Bitset.h"
+#include "zydis/Zycore/LibC.h"
+
+/* ============================================================================================== */
+/* Internal constants */
+/* ============================================================================================== */
+
+#define ZYAN_BITSET_GROWTH_FACTOR 2
+#define ZYAN_BITSET_SHRINK_THRESHOLD 2
+
+/* ============================================================================================== */
+/* Internal macros */
+/* ============================================================================================== */
+
+/**
+ * Computes the smallest integer value not less than `x`.
+ *
+ * @param x The value.
+ *
+ * @return The smallest integer value not less than `x`.
+ */
+#define ZYAN_BITSET_CEIL(x) \
+ (((x) == ((ZyanU32)(x))) ? (ZyanU32)(x) : ((ZyanU32)(x)) + 1)
+
+/**
+ * Converts bits to bytes.
+ *
+ * @param x The value in bits.
+ *
+ * @return The amount of bytes needed to fit `x` bits.
+ */
+#define ZYAN_BITSET_BITS_TO_BYTES(x) \
+ ZYAN_BITSET_CEIL((x) / 8)
+
+/**
+ * Returns the offset of the given bit.
+ *
+ * @param index The bit index.
+ *
+ * @return The offset of the given bit.
+ */
+#define ZYAN_BITSET_BIT_OFFSET(index) \
+ (7 - ((index) % 8))
+
+/* ============================================================================================== */
+/* Internal functions */
+/* ============================================================================================== */
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Helper functions */
+/* ---------------------------------------------------------------------------------------------- */
+
+/**
+ * Initializes the given `vector` with `count` "zero"-bytes.
+ *
+ * @param vector A pointer to the `ZyanVector` instance.
+ * @param count The number of bytes.
+ *
+ * @return A zyan status code.
+ */
+static ZyanStatus ZyanBitsetInitVectorElements(ZyanVector* vector, ZyanUSize count)
+{
+ ZYAN_ASSERT(vector);
+
+ static const ZyanU8 zero = 0;
+ for (ZyanUSize i = 0; i < count; ++i)
+ {
+ ZYAN_CHECK(ZyanVectorPushBack(vector, &zero));
+ }
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Byte operations */
+/* ---------------------------------------------------------------------------------------------- */
+
+static ZyanStatus ZyanBitsetOperationAND(ZyanU8* b1, const ZyanU8* b2)
+{
+ *b1 &= *b2;
+ return ZYAN_STATUS_SUCCESS;
+}
+
+static ZyanStatus ZyanBitsetOperationOR (ZyanU8* b1, const ZyanU8* b2)
+{
+ *b1 |= *b2;
+ return ZYAN_STATUS_SUCCESS;
+}
+
+static ZyanStatus ZyanBitsetOperationXOR(ZyanU8* b1, const ZyanU8* b2)
+{
+ *b1 ^= *b2;
+ return ZYAN_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+/* ============================================================================================== */
+/* Exported functions */
+/* ============================================================================================== */
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Constructor and destructor */
+/* ---------------------------------------------------------------------------------------------- */
+
+#ifndef ZYAN_NO_LIBC
+
+ZyanStatus ZyanBitsetInit(ZyanBitset* bitset, ZyanUSize count)
+{
+ return ZyanBitsetInitEx(bitset, count, ZyanAllocatorDefault(), ZYAN_BITSET_GROWTH_FACTOR,
+ ZYAN_BITSET_SHRINK_THRESHOLD);
+}
+
+#endif // ZYAN_NO_LIBC
+
+ZyanStatus ZyanBitsetInitEx(ZyanBitset* bitset, ZyanUSize count, ZyanAllocator* allocator,
+ ZyanU8 growth_factor, ZyanU8 shrink_threshold)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ const ZyanU32 bytes = ZYAN_BITSET_BITS_TO_BYTES(count);
+
+ bitset->size = count;
+ ZYAN_CHECK(ZyanVectorInitEx(&bitset->bits, sizeof(ZyanU8), bytes, ZYAN_NULL, allocator,
+ growth_factor, shrink_threshold));
+ ZYAN_CHECK(ZyanBitsetInitVectorElements(&bitset->bits, bytes));
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetInitBuffer(ZyanBitset* bitset, ZyanUSize count, void* buffer,
+ ZyanUSize capacity)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ const ZyanU32 bytes = ZYAN_BITSET_BITS_TO_BYTES(count);
+ if (capacity < bytes)
+ {
+ return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
+ }
+
+ bitset->size = count;
+ ZYAN_CHECK(ZyanVectorInitCustomBuffer(&bitset->bits, sizeof(ZyanU8), buffer, capacity,
+ ZYAN_NULL));
+ ZYAN_CHECK(ZyanBitsetInitVectorElements(&bitset->bits, bytes));
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetDestroy(ZyanBitset* bitset)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ return ZyanVectorDestroy(&bitset->bits);
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Logical operations */
+/* ---------------------------------------------------------------------------------------------- */
+
+ZyanStatus ZyanBitsetPerformByteOperation(ZyanBitset* destination, const ZyanBitset* source,
+ ZyanBitsetByteOperation operation)
+{
+ if (!destination || !source || !operation)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ ZyanUSize s1;
+ ZyanUSize s2;
+ ZYAN_CHECK(ZyanVectorGetSize(&destination->bits, &s1));
+ ZYAN_CHECK(ZyanVectorGetSize(&source->bits, &s2));
+
+ const ZyanUSize min = ZYAN_MIN(s1, s2);
+ for (ZyanUSize i = 0; i < min; ++i)
+ {
+ ZyanU8* v1;
+ const ZyanU8* v2;
+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&destination->bits, i, (void**)&v1));
+ ZYAN_CHECK(ZyanVectorGetPointer(&source->bits, i, (const void**)&v2));
+
+ ZYAN_ASSERT(v1);
+ ZYAN_ASSERT(v2);
+
+ ZYAN_CHECK(operation(v1, v2));
+ }
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetAND(ZyanBitset* destination, const ZyanBitset* source)
+{
+ return ZyanBitsetPerformByteOperation(destination, source, ZyanBitsetOperationAND);
+}
+
+ZyanStatus ZyanBitsetOR (ZyanBitset* destination, const ZyanBitset* source)
+{
+ return ZyanBitsetPerformByteOperation(destination, source, ZyanBitsetOperationOR );
+}
+
+ZyanStatus ZyanBitsetXOR(ZyanBitset* destination, const ZyanBitset* source)
+{
+ return ZyanBitsetPerformByteOperation(destination, source, ZyanBitsetOperationXOR);
+}
+
+ZyanStatus ZyanBitsetFlip(ZyanBitset* bitset)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ ZyanUSize size;
+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
+ for (ZyanUSize i = 0; i < size; ++i)
+ {
+ ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, i, (void**)&value));
+ *value = ~(*value);
+ }
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Bit access */
+/* ---------------------------------------------------------------------------------------------- */
+
+ZyanStatus ZyanBitsetSet(ZyanBitset* bitset, ZyanUSize index)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+ if (index >= bitset->size)
+ {
+ return ZYAN_STATUS_OUT_OF_RANGE;
+ }
+
+ ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, index / 8, (void**)&value));
+
+ *value |= (1 << ZYAN_BITSET_BIT_OFFSET(index));
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetReset(ZyanBitset* bitset, ZyanUSize index)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+ if (index >= bitset->size)
+ {
+ return ZYAN_STATUS_OUT_OF_RANGE;
+ }
+
+ ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, index / 8, (void**)&value));
+ *value &= ~(1 << ZYAN_BITSET_BIT_OFFSET(index));
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetAssign(ZyanBitset* bitset, ZyanUSize index, ZyanBool value)
+{
+ if (value)
+ {
+ return ZyanBitsetSet(bitset, index);
+ }
+ return ZyanBitsetReset(bitset, index);
+}
+
+ZyanStatus ZyanBitsetToggle(ZyanBitset* bitset, ZyanUSize index)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+ if (index >= bitset->size)
+ {
+ return ZYAN_STATUS_OUT_OF_RANGE;
+ }
+
+ ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, index / 8, (void**)&value));
+ *value ^= (1 << ZYAN_BITSET_BIT_OFFSET(index));
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetTest(ZyanBitset* bitset, ZyanUSize index)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+ if (index >= bitset->size)
+ {
+ return ZYAN_STATUS_OUT_OF_RANGE;
+ }
+
+ const ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, index / 8, (const void**)&value));
+ if ((*value & (1 << ZYAN_BITSET_BIT_OFFSET(index))) == 0)
+ {
+ return ZYAN_STATUS_FALSE;
+ }
+ return ZYAN_STATUS_TRUE;
+}
+
+ZyanStatus ZyanBitsetTestMSB(ZyanBitset* bitset)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ return ZyanBitsetTest(bitset, bitset->size - 1);
+}
+
+ZyanStatus ZyanBitsetTestLSB(ZyanBitset* bitset)
+{
+ return ZyanBitsetTest(bitset, 0);
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+ZyanStatus ZyanBitsetSetAll(ZyanBitset* bitset)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ ZyanUSize size;
+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
+ for (ZyanUSize i = 0; i < size; ++i)
+ {
+ ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, i, (void**)&value));
+ *value = 0xFF;
+ }
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetResetAll(ZyanBitset* bitset)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ ZyanUSize size;
+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
+ for (ZyanUSize i = 0; i < size; ++i)
+ {
+ ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointerMutable(&bitset->bits, i, (void**)&value));
+ *value = 0x00;
+ }
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Size management */
+/* ---------------------------------------------------------------------------------------------- */
+
+ZyanStatus ZyanBitsetPush(ZyanBitset* bitset, ZyanBool value)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ if ((bitset->size++ % 8) == 0)
+ {
+ static const ZyanU8 zero = 0;
+ ZYAN_CHECK(ZyanVectorPushBack(&bitset->bits, &zero));
+ }
+
+ return ZyanBitsetAssign(bitset, bitset->size - 1, value);
+}
+
+ZyanStatus ZyanBitsetPop(ZyanBitset* bitset)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ if ((--bitset->size % 8) == 0)
+ {
+ return ZyanVectorPopBack(&bitset->bits);
+ }
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetClear(ZyanBitset* bitset)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ bitset->size = 0;
+ return ZyanVectorClear(&bitset->bits);
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Memory management */
+/* ---------------------------------------------------------------------------------------------- */
+
+ZyanStatus ZyanBitsetReserve(ZyanBitset* bitset, ZyanUSize count)
+{
+ return ZyanVectorReserve(&bitset->bits, ZYAN_BITSET_BITS_TO_BYTES(count));
+}
+
+ZyanStatus ZyanBitsetShrinkToFit(ZyanBitset* bitset)
+{
+ return ZyanVectorShrinkToFit(&bitset->bits);
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+/* Information */
+/* ---------------------------------------------------------------------------------------------- */
+
+ZyanStatus ZyanBitsetGetSize(const ZyanBitset* bitset, ZyanUSize* size)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ *size = bitset->size;
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetGetCapacity(const ZyanBitset* bitset, ZyanUSize* capacity)
+{
+ ZYAN_CHECK(ZyanBitsetGetCapacityBytes(bitset, capacity));
+ *capacity *= 8;
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetGetSizeBytes(const ZyanBitset* bitset, ZyanUSize* size)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ return ZyanVectorGetSize(&bitset->bits, size);
+}
+
+ZyanStatus ZyanBitsetGetCapacityBytes(const ZyanBitset* bitset, ZyanUSize* capacity)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ return ZyanVectorGetCapacity(&bitset->bits, capacity);
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+ZyanStatus ZyanBitsetCount(const ZyanBitset* bitset, ZyanUSize* count)
+{
+ if (!bitset || !count)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ *count = 0;
+
+ ZyanUSize size;
+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
+ for (ZyanUSize i = 0; i < size; ++i)
+ {
+ ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value));
+
+ ZyanU8 popcnt = *value;
+ popcnt = (popcnt & 0x55) + ((popcnt >> 1) & 0x55);
+ popcnt = (popcnt & 0x33) + ((popcnt >> 2) & 0x33);
+ popcnt = (popcnt & 0x0F) + ((popcnt >> 4) & 0x0F);
+
+ *count += popcnt;
+ }
+
+ *count = ZYAN_MIN(*count, bitset->size);
+
+ return ZYAN_STATUS_SUCCESS;
+}
+
+ZyanStatus ZyanBitsetAll(const ZyanBitset* bitset)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ ZyanUSize size;
+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
+ for (ZyanUSize i = 0; i < size; ++i)
+ {
+ ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value));
+ if (i < (size - 1))
+ {
+ if (*value != 0xFF)
+ {
+ return ZYAN_STATUS_FALSE;
+ }
+ } else
+ {
+ const ZyanU8 mask = ~(8 - (bitset->size % 8));
+ if ((*value & mask) != mask)
+ {
+ return ZYAN_STATUS_FALSE;
+ }
+ }
+ }
+
+ return ZYAN_STATUS_TRUE;
+}
+
+ZyanStatus ZyanBitsetAny(const ZyanBitset* bitset)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ ZyanUSize size;
+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
+ for (ZyanUSize i = 0; i < size; ++i)
+ {
+ ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value));
+ if (i < (size - 1))
+ {
+ if (*value != 0x00)
+ {
+ return ZYAN_STATUS_TRUE;
+ }
+ } else
+ {
+ const ZyanU8 mask = ~(8 - (bitset->size % 8));
+ if ((*value & mask) != 0x00)
+ {
+ return ZYAN_STATUS_TRUE;
+ }
+ }
+ }
+
+ return ZYAN_STATUS_FALSE;
+}
+
+ZyanStatus ZyanBitsetNone(const ZyanBitset* bitset)
+{
+ if (!bitset)
+ {
+ return ZYAN_STATUS_INVALID_ARGUMENT;
+ }
+
+ ZyanUSize size;
+ ZYAN_CHECK(ZyanVectorGetSize(&bitset->bits, &size));
+ for (ZyanUSize i = 0; i < size; ++i)
+ {
+ ZyanU8* value;
+ ZYAN_CHECK(ZyanVectorGetPointer(&bitset->bits, i, (const void**)&value));
+ if (i < (size - 1))
+ {
+ if (*value != 0x00)
+ {
+ return ZYAN_STATUS_FALSE;
+ }
+ } else
+ {
+ const ZyanU8 mask = ~(8 - (bitset->size % 8));
+ if ((*value & mask) != 0x00)
+ {
+ return ZYAN_STATUS_FALSE;
+ }
+ }
+ }
+
+ return ZYAN_STATUS_TRUE;
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+//ZyanStatus ZyanBitsetToU32(const ZyanBitset* bitset, ZyanU32* value)
+//{
+// if (!bitset)
+// {
+// return ZYAN_STATUS_INVALID_ARGUMENT;
+// }
+// if (bitset->size > 32)
+// {
+// return ZYAN_STATUS_INVALID_OPERATION;
+// }
+//
+// // TODO:
+//
+// return ZYAN_STATUS_SUCCESS;
+//}
+//
+//ZyanStatus ZyanBitsetToU64(const ZyanBitset* bitset, ZyanU64* value)
+//{
+// if (!bitset)
+// {
+// return ZYAN_STATUS_INVALID_ARGUMENT;
+// }
+// if (bitset->size > 64)
+// {
+// return ZYAN_STATUS_INVALID_OPERATION;
+// }
+//
+// // TODO:
+//
+// return ZYAN_STATUS_SUCCESS;
+//}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+/* ============================================================================================== */