summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2022-12-09 07:57:36 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2022-12-09 07:57:52 (GMT)
commitc27f884ec1d18d9cff0d19d6ba8de1dd54d991c4 (patch)
tree6549b81a21142c6e5ace2ba12039d45b6cd12084 /src
parent6dea5e4fed979cb57f3dbc0c9144f1ff1854b800 (diff)
Allow OR operations in bit fields at a given position.
Diffstat (limited to 'src')
-rw-r--r--src/common/bits.c138
-rw-r--r--src/common/bits.h6
2 files changed, 143 insertions, 1 deletions
diff --git a/src/common/bits.c b/src/common/bits.c
index d3b45bb..590c318 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -40,6 +40,8 @@ struct _bitfield_t
size_t length; /* Nombre de bits représentés */
size_t requested; /* Nombre de mots alloués */
+ bool default_state; /* Etat d'initialisation */
+
unsigned long bits[0]; /* Mémoire d'accès associée */
};
@@ -108,6 +110,8 @@ bitfield_t *create_bit_field(size_t length, bool state)
result = _create_bit_field(length);
+ result->default_state = state;
+
if (state)
set_all_in_bit_field(result);
else
@@ -186,6 +190,83 @@ void copy_bit_field(bitfield_t *dest, const bitfield_t *src)
/******************************************************************************
* *
+* Paramètres : field = champ de bits à modifier. [OUT] *
+* length = nouveau nombre de bits du champ à représenter. *
+* *
+* Description : Redimensionne un champ de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void resize_bit_field(bitfield_t **field, size_t length)
+{
+ bitfield_t *_field; /* Commodité d'accès */
+ size_t requested; /* Nombre de mots à allouer */
+ size_t base; /* Allocation de base en octets*/
+ size_t remaining; /* Nombre de derniers bits */
+ size_t last; /* Dernier mot utilisé */
+ unsigned long mask; /* Masque d'initialisation */
+ size_t i; /* Boucle de parcours */
+
+ _field = *field;
+
+ if (_field->length != length)
+ {
+ /* Redimensionnement */
+
+ requested = length / (sizeof(unsigned long) * 8);
+ if (length % (sizeof(unsigned long) * 8) != 0) requested++;
+
+ base = sizeof(bitfield_t) + requested * sizeof(unsigned long);
+
+ *field = realloc(_field, base);
+ _field = *field;
+
+ /* Initialisation, si nécessaire */
+
+ if (_field->length < length)
+ {
+ last = _field->length / (sizeof(unsigned long) * 8);
+ remaining = _field->length % (sizeof(unsigned long) * 8);
+
+ if (remaining != 0)
+ {
+ mask = (1ul << remaining) - 1;
+
+ if (_field->default_state)
+ _field->bits[last] |= ~mask;
+ else
+ _field->bits[last] &= mask;
+
+ last++;
+
+ }
+
+ for (i = last; i < requested; i++)
+ {
+ if (_field->default_state)
+ _field->bits[i] = ~0ul;
+ else
+ _field->bits[i] = 0ul;
+ }
+
+ }
+
+ /* Actualisation des tailles */
+
+ _field->length = length;
+ _field->requested = requested;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : field = champ de bits à consulter. *
* *
* Description : Indique la taille d'un champ de bits donné. *
@@ -435,6 +516,61 @@ void or_bit_field(bitfield_t *dest, const bitfield_t *src)
/******************************************************************************
* *
+* Paramètres : dest = champ de bits à modifier. *
+* src = champ de bits à utiliser pour l'opération. *
+* first = point de départ pour l'opération à réaliser. *
+* *
+* Description : Réalise une opération OU logique entre deux champs de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void or_bit_field_at(bitfield_t *dest, const bitfield_t *src, size_t first)
+{
+ size_t start; /* Mot de départ dans le champ */
+ size_t offset; /* Décalage des mots à basculer*/
+ size_t remaining; /* Taille du dernier tronçon */
+ unsigned long finalcut; /* Limitation du mot final */
+ size_t i; /* Boucle de parcours */
+ unsigned long word; /* Mot reconstituté à tester */
+
+ assert(dest->length <= (first + src->length));
+
+ start = first / (sizeof(unsigned long) * 8);
+ offset = first % (sizeof(unsigned long) * 8);
+
+ remaining = (first + src->length) % (sizeof(unsigned long) * 8);
+
+ if (remaining == 0)
+ finalcut = ~0ul;
+ else
+ finalcut = (1ul << remaining) - 1;
+
+ for (i = 0; i < (src->requested + 1); i++)
+ {
+ if (i < src->requested)
+ word = src->bits[i] << offset;
+ else
+ word = 0;
+
+ if (i > 0)
+ word |= src->bits[i - 1] >> (sizeof(unsigned long) * 8 - offset);
+
+ if (i == src->requested)
+ word &= finalcut;
+
+ dest->bits[start + i] |= word;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : field = champ de bits à consulter. *
* n = indice du bit à traiter. *
* *
@@ -610,7 +746,7 @@ static bool test_state_within_bit_field(const bitfield_t *field, size_t first, c
{
word = field->bits[windex] >> offset;
if ((windex + 1) < field->requested)
- word |= field->bits[start + i + 1] << (sizeof(unsigned long) * 8 - offset);
+ word |= field->bits[windex + 1] << (sizeof(unsigned long) * 8 - offset);
}
bitmask = mask->bits[i];
diff --git a/src/common/bits.h b/src/common/bits.h
index fb231d5..58fa0fe 100644
--- a/src/common/bits.h
+++ b/src/common/bits.h
@@ -45,6 +45,9 @@ void delete_bit_field(bitfield_t *);
/* Copie un champ de bits dans un autre. */
void copy_bit_field(bitfield_t *, const bitfield_t *);
+/* Redimensionne un champ de bits. */
+void resize_bit_field(bitfield_t **, size_t);
+
/* Indique la taille d'un champ de bits donné. */
size_t get_bit_field_size(const bitfield_t *);
@@ -69,6 +72,9 @@ void and_bit_field(bitfield_t *, const bitfield_t *);
/* Réalise une opération OU logique entre deux champs de bits. */
void or_bit_field(bitfield_t *, const bitfield_t *);
+/* Réalise une opération OU logique entre deux champs de bits. */
+void or_bit_field_at(bitfield_t *, const bitfield_t *, size_t);
+
/* Détermine si un bit est à 1 dans un champ de bits. */
bool test_in_bit_field(const bitfield_t *, size_t);