Bit manipulation/fr: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: Bit manipulation/fr
| Old | New | Line | |
|---|---|---|---|
| 1 | + | \ | |
| 2 | + | \ | |
| 3 | + | ||
| 4 | + | ## Opération masquées | |
| 5 | + | ||
| 6 | + | Ceci est une approche bas niveau basique pour manier les manipulation de bit. Le principale avantage est que les opérations peuvent être réalisées sur un groupes de bits en une seule fois. Mais l'utilisateur doit faire face à ces opérations par lui-même. Un autre problème est l'intervalle maximal des valeurs utilisées dans les paramètres de fonction. Il faut donc séparer les implémentations de chaque type ordinal pour de meilleures performances (contrairement à ce qui peut être fait en C en utilisant le préprocesseur). | |
| 7 | + | ||
| 8 | + | (NdT : une solution peut résider dans l'emploi de fonctions génériques, non développées ici.) | |
| 9 | + | ||
| 10 | + | ``` pascal | |
| 11 | + | procedure ClearBit(var Value: QWord; Index: Byte); | |
| 12 | + | begin | |
| 13 | + | Value := Value and ((QWord(1) shl Index) xor High(QWord)); | |
| 14 | + | end; | |
| 15 | + | ||
| 16 | + | procedure SetBit(var Value: QWord; Index: Byte); | |
| 17 | + | begin | |
| 18 | + | Value:= Value or (QWord(1) shl Index); | |
| 19 | + | end; | |
| 20 | + | ||
| 21 | + | procedure PutBit(var Value: QWord; Index: Byte; State: Boolean); | |
| 22 | + | begin | |
| 23 | + | Value := (Value and ((QWord(1) shl Index) xor High(QWord))) or (QWord(State) shl Index); | |
| 24 | + | end; | |
| 25 | + | ||
| 26 | + | function GetBit(Value: QWord; Index: Byte): Boolean; | |
| 27 | + | begin | |
| 28 | + | Result := ((Value shr Index) and 1) = 1; | |
| 29 | + | end; | |
| 30 | + | ``` | |
| 31 | + | ||
| 32 | + | ## Enregistrement bit-paqueté (Bitpacked) | |
| 33 | + | ||
| 34 | + | FPC a une extension utile qui permet non seulement le paquetage des enregistrements par octet mais aussi le paquetage par bit. Ceci permet de définir non seulement des structures de bits en utilisant le type booléen ou des intervalles 0..1 mais aussi des champs à n états ou n-bits dans des enregistrements p.ex. le type intervalle 0..3 pour 2 bits. L'utilisation conjointe d'une telle structure de bits et d'un enregistrement avec variante permet d'accéder à la mémoire soit par octet soit par bit individuel. | |
| 35 | + | ||
| 36 | + | ``` pascal | |
| 37 | + | TByteBits = bitpacked record | |
| 38 | + | Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7: Boolean; | |
| 39 | + | end; | |
| 40 | + | ||
| 41 | + | TByteEx = packed record | |
| 42 | + | case Integer of | |
| 43 | + | 0: (ByteAccess: Byte); | |
| 44 | + | 1: (BitAccess: TByteBits); | |
| 45 | + | end; | |
| 46 | + | ||
| 47 | + | TSomeBitLevelStructure = bitpacked record | |
| 48 | + | OneBit: 0..1; | |
| 49 | + | TwoBits: 0..3; | |
| 50 | + | FourBits: 0..15; | |
| 51 | + | EightBits: 0..255 | |
| 52 | + | end; | |
| 53 | + | ``` | |
| 54 | + | ||
| 55 | + | NB : on accède au bit via des identificateurs. | |
| 56 | + | ||
| 57 | + | Le paquetage par bit peut être contrôlé en utilisant la directive [\$BITPACKING](http://www.freepascal.org/docs-html/prog/progsu6.html). | |
| 58 | + | ||
| 59 | + | ## Type ensemble | |
| 60 | + | ||
| 61 | + | Parce que les ensembles sont basiquement des tableaux de tous les états qui sont des types booléens, il est donc possible de les utiliser comme tableaux de bits. Mais cela nécessite l'emploi de la directive de compilation [\$PACKENUM](http://www.freepascal.org/docs-html/prog/progsu57.html#x63-620001.1.57) pour modifier la taille de l'ensemble. Il y aussi certaines limitations sur la taille maximale d'un ensemble. | |
| 62 | + | ||
| 63 | + | ``` pascal | |
| 64 | + | {$packset 1} | |
| 65 | + | {$packenum 1} | |
| 66 | + | ||
| 67 | + | type | |
| 68 | + | TByteBits = set of (Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7); | |
| 69 | + | ``` | |
| 70 | + | ||
| 71 | + | ## TBits | |
| 72 | + | ||
| 73 | + | Cette classe fait partie de la bibliothèque RTL de FPC, contenue dans l'unité Classes et s'emploie de manière similaire à celle de Delphi. Elle fournit seulement quelques méthodes pour les manipulations de bits. | |
| 74 | + | ||
| 75 | + | ``` pascal | |
| 76 | + | TBits = class(TObject) | |
| 77 | + | public | |
| 78 | + | constructor Create(TheSize : longint = 0); virtual; | |
| 79 | + | destructor Destroy; override; | |
| 80 | + | function GetFSize : longint; | |
| 81 | + | procedure SetOn(Bit : longint); | |
| 82 | + | procedure Clear(Bit : longint); | |
| 83 | + | procedure Clearall; | |
| 84 | + | procedure AndBits(BitSet : TBits); | |
| 85 | + | procedure OrBits(BitSet : TBits); | |
| 86 | + | procedure XorBits(BitSet : TBits); | |
| 87 | + | procedure NotBits(BitSet : TBits); | |
| 88 | + | function Get(Bit : longint) : boolean; | |
| 89 | + | procedure Grow(NBit : longint); | |
| 90 | + | function Equals(Obj : TObject): Boolean; override; overload; | |
| 91 | + | function Equals(BitSet : TBits) : Boolean; overload; | |
| 92 | + | procedure SetIndex(Index : longint); | |
| 93 | + | function FindFirstBit(State : boolean) : longint; | |
| 94 | + | function FindNextBit : longint; | |
| 95 | + | function FindPrevBit : longint; | |
| 96 | + | ||
| 97 | + | { functions and properties to match TBits class } | |
| 98 | + | function OpenBit: longint; | |
| 99 | + | property Bits[Bit: longint]: Boolean read get write SetBit; default; | |
| 100 | + | property Size: longint read FBSize write setSize; | |
| 101 | + | end; | |
| 102 | + | ``` | |
| 103 | + | ||
| 104 | + | NB : | |
| 105 | + | ||
| 106 | + | - Pas de limitation de taille comme avec les ensembles, | |
| 107 | + | - les bits sont accessibles uniquement de manière ordinale. | |
| 108 | + | ||
| 109 | + | ## Propriété enregistrement et valeur index | |
| 110 | + | ||
| 111 | + | Une autre implémentation intéressante des structures alignées sur les bits peur être utilisée avec la capacité des enregistrements avancés (FPC 2.6.0+). Pour toutes les propriétés, vous devez utiliser un accesseur en écriture et un en lecture qui peuvent gérer les manipulations générales des bits et définir l'index qui est transmis à ces méthodes. Pour plus d'informations, reportez-vous aux [propriétés indexées](http://www.freepascal.org/docs-html/ref/refsu31.html). Parce que l'index de propriété est unique, il a été divisé en deux paramètres pour décrire, la position et la taille de la valeur de bit. Dans le cas de l'exemple suivant, le décalage peut être de 0..255 et la taille de la valeur 0..255 bits. Un autre problème est que vous devez vous assurer que les composants définis dans la structure ne se chevaucheront pas. | |
| 112 | + | ||
| 113 | + | ``` pascal | |
| 114 | + | {$mode delphi} | |
| 115 | + | ||
| 116 | + | TSomeBitStructure = record | |
| 117 | + | private | |
| 118 | + | RawData: Word; | |
| 119 | + | function GetBits(const AIndex: Integer): Integer; inline; | |
| 120 | + | procedure SetBits(const AIndex: Integer; const AValue: Integer); inline; | |
| 121 | + | public | |
| 122 | + | // High byte of index offset, low byte of index is bit count | |
| 123 | + | property OneBit: Integer index $0001 read GetBits write SetBits; | |
| 124 | + | property TwoBits: Integer index $0102 read GetBits write SetBits; | |
| 125 | + | property FourBits: Integer index $0304 read GetBits write SetBits; | |
| 126 | + | property EightBits: Integer index $0708 read GetBits write SetBits; | |
| 127 | + | end; | |
| 128 | + | ||
| 129 | + | {$OPTIMIZATION ON} | |
| 130 | + | {$OVERFLOWCHECKS OFF} | |
| 131 | + | function TSomeBitStructure.GetBits(const AIndex: Integer): Integer; | |
| 132 | + | var | |
| 133 | + | Offset: Integer; | |
| 134 | + | BitCount: Integer; | |
| 135 | + | Mask: Integer; | |
| 136 | + | begin | |
| 137 | + | BitCount := AIndex and $FF; | |
| 138 | + | Offset := AIndex shr 8; | |
| 139 | + | Mask := ((1 shl BitCount) - 1); | |
| 140 | + | Result := (RawData shr Offset) and Mask; | |
| 141 | + | end; | |
| 142 | + | ||
| 143 | + | procedure TSomeBitStructure.SetBits(const AIndex: Integer; const AValue: Integer); | |
| 144 | + | var | |
| 145 | + | Offset: Integer; | |
| 146 | + | BitCount: Integer; | |
| 147 | + | Mask: Integer; | |
| 148 | + | begin | |
| 149 | + | BitCount := AIndex and $FF; | |
| 150 | + | Offset := AIndex shr 8; | |
| 151 | + | Mask := ((1 shl BitCount) - 1); | |
| 152 | + | Assert(aValue <= Mask); | |
| 153 | + | RawData := (RawData and (not (Mask shl Offset))) or (AValue shl Offset); | |
| 154 | + | end; | |
| 155 | + | ``` | |
| 156 | + | ||
| 157 | + | --- | |
| 158 | + | *From the Free Pascal wiki, page "Bit manipulation/fr", as it stood on 2020-02-10 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
