diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2022-12-09 07:57:36 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2022-12-09 07:57:52 (GMT) |
commit | c27f884ec1d18d9cff0d19d6ba8de1dd54d991c4 (patch) | |
tree | 6549b81a21142c6e5ace2ba12039d45b6cd12084 /src | |
parent | 6dea5e4fed979cb57f3dbc0c9144f1ff1854b800 (diff) |
Allow OR operations in bit fields at a given position.
Diffstat (limited to 'src')
-rw-r--r-- | src/common/bits.c | 138 | ||||
-rw-r--r-- | src/common/bits.h | 6 |
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); |