Line data Source code
1 : /* Copyright 2017 noseglasses <shinynoseglasses@gmail.com>
2 : *
3 : * This program is free software: you can redistribute it and/or modify
4 : * it under the terms of the GNU Lesser General Public License as published by
5 : * the Free Software Foundation, either version 3 of the License, or
6 : * (at your option) any later version.
7 : *
8 : * This program is distributed in the hope that it will be useful,
9 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 : * GNU Lesser General Public License for more details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 : */
16 :
17 : #include "ppg_bitfield.h"
18 : #include "detail/ppg_malloc_detail.h"
19 :
20 : #include <string.h>
21 : #include <stdlib.h>
22 :
23 56 : void ppg_bitfield_init(PPG_Bitfield *bitfield)
24 : {
25 56 : bitfield->n_bits = 0;
26 56 : bitfield->bitarray = NULL;
27 56 : }
28 :
29 128 : PPG_Count ppg_bitfield_get_num_cells_from_bits(uint8_t n_bits)
30 : {
31 128 : PPG_Count cells = n_bits/(8*sizeof(PPG_Bitfield_Storage_Type));
32 128 : PPG_Count bits = n_bits%(8*sizeof(PPG_Bitfield_Storage_Type));
33 :
34 128 : if(bits != 0) {
35 128 : cells += 1;
36 : }
37 :
38 128 : return cells;
39 : }
40 :
41 72 : PPG_Count ppg_bitfield_get_num_cells(PPG_Bitfield *bitfield)
42 : {
43 72 : return ppg_bitfield_get_num_cells_from_bits(bitfield->n_bits);
44 : }
45 :
46 0 : void ppg_bitfield_clear(PPG_Bitfield *bitfield)
47 : {
48 0 : if(!bitfield->bitarray) { return; }
49 :
50 0 : PPG_Count cells = ppg_bitfield_get_num_cells_from_bits(bitfield->n_bits);
51 :
52 0 : memset(bitfield->bitarray, 0, cells);
53 : }
54 :
55 4344 : bool ppg_bitfield_get_bit(PPG_Bitfield *bitfield,
56 : PPG_Count pos)
57 : {
58 4344 : PPG_Count cell = pos/(8*sizeof(PPG_Bitfield_Storage_Type));
59 4344 : PPG_Count bit = pos%(8*sizeof(PPG_Bitfield_Storage_Type));
60 :
61 4344 : return bitfield->bitarray[cell] & (1 << bit);
62 : }
63 :
64 1051 : void ppg_bitfield_set_bit(PPG_Bitfield *bitfield,
65 : PPG_Count pos,
66 : bool state)
67 : {
68 1051 : PPG_Count cell = pos/(8*sizeof(PPG_Bitfield_Storage_Type));
69 1051 : PPG_Count bit = pos%(8*sizeof(PPG_Bitfield_Storage_Type));
70 :
71 1051 : if(state) {
72 :
73 : // Set the specific bit
74 : //
75 323 : bitfield->bitarray[cell] |= (PPG_Bitfield_Storage_Type)(1 << bit);
76 : }
77 : else {
78 :
79 : // Clear the specific bit
80 : //
81 728 : bitfield->bitarray[cell] &= (PPG_Bitfield_Storage_Type)~(1 << bit);
82 : }
83 1051 : }
84 :
85 56 : void ppg_bitfield_resize(PPG_Bitfield *bitfield,
86 : uint8_t n_bits,
87 : bool keep_content)
88 : {
89 56 : if(bitfield->n_bits != n_bits) {
90 :
91 56 : PPG_Count cells = ppg_bitfield_get_num_cells_from_bits(n_bits);
92 :
93 56 : if(bitfield->bitarray) {
94 :
95 0 : uint8_t *new_bitarray
96 0 : = (uint8_t*)PPG_MALLOC(cells*sizeof(PPG_Bitfield_Storage_Type));
97 :
98 : // Copy the content of the previous bitarray
99 : //
100 0 : if(keep_content) {
101 :
102 0 : PPG_Count old_cells
103 0 : = ppg_bitfield_get_num_cells_from_bits(bitfield->n_bits);
104 :
105 0 : memcpy(new_bitarray, bitfield->bitarray, old_cells);
106 : }
107 :
108 0 : free(bitfield->bitarray);
109 :
110 0 : bitfield->bitarray = new_bitarray;
111 : }
112 : else {
113 : bitfield->bitarray
114 56 : = (uint8_t*)PPG_MALLOC(cells*sizeof(PPG_Bitfield_Storage_Type));
115 :
116 112 : for(size_t cell_id = 0; cell_id < cells; ++cell_id) {
117 56 : bitfield->bitarray[cell_id] = 0;
118 : }
119 : }
120 :
121 56 : bitfield->n_bits = n_bits;
122 : }
123 56 : }
124 :
125 0 : void ppg_bitfield_copy(PPG_Bitfield *source, PPG_Bitfield *target)
126 : {
127 0 : if(source->bitarray == NULL) {
128 0 : ppg_bitfield_destroy(target);
129 0 : return;
130 : }
131 :
132 0 : if(target->n_bits != source->n_bits) {
133 :
134 0 : ppg_bitfield_resize(target, source->n_bits,
135 : false /* no need to keep content as it is overwritten */);
136 : }
137 :
138 0 : PPG_Count cells = ppg_bitfield_get_num_cells_from_bits(source->n_bits);
139 :
140 0 : memcpy(target->bitarray, source->bitarray, cells);
141 : }
142 :
143 94 : void ppg_bitfield_destroy(PPG_Bitfield *bitfield)
144 : {
145 94 : if(bitfield->bitarray) {
146 56 : free(bitfield->bitarray);
147 56 : bitfield->bitarray = NULL;
148 56 : bitfield->n_bits = 0;
149 : }
150 94 : }
|