├── .gitattributes ├── .github └── workflows │ └── tg-send.yml ├── LICENSE ├── README.md ├── README_EN.md ├── examples ├── flags │ └── flags.ino └── test │ └── test.ino ├── keywords.txt ├── library.properties └── src ├── BitFlags.h └── BitPack.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/tg-send.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Telegram Message 3 | on: 4 | release: 5 | types: [published] 6 | jobs: 7 | build: 8 | name: Send Message 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: send telegram message on push 12 | uses: appleboy/telegram-action@master 13 | with: 14 | to: ${{ secrets.TELEGRAM_TO }} 15 | token: ${{ secrets.TELEGRAM_TOKEN }} 16 | disable_web_page_preview: true 17 | message: | 18 | ${{ github.event.repository.name }} v${{ github.event.release.tag_name }} 19 | ${{ github.event.release.body }} 20 | https://github.com/${{ github.repository }} 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 AlexGyver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![latest](https://img.shields.io/github/v/release/GyverLibs/BitPack.svg?color=brightgreen)](https://github.com/GyverLibs/BitPack/releases/latest/download/BitPack.zip) 2 | [![PIO](https://badges.registry.platformio.org/packages/gyverlibs/library/BitPack.svg)](https://registry.platformio.org/libraries/gyverlibs/BitPack) 3 | [![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/) 4 | [![Foo](https://img.shields.io/badge/%E2%82%BD%24%E2%82%AC%20%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B0%D1%82%D1%8C-%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B0-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/) 5 | [![Foo](https://img.shields.io/badge/README-ENGLISH-blueviolet.svg?style=flat-square)](https://github-com.translate.goog/GyverLibs/BitPack?_x_tr_sl=ru&_x_tr_tl=en) 6 | 7 | [![Foo](https://img.shields.io/badge/ПОДПИСАТЬСЯ-НА%20ОБНОВЛЕНИЯ-brightgreen.svg?style=social&logo=telegram&color=blue)](https://t.me/GyverLibs) 8 | 9 | # BitPack 10 | Библиотека для упаковки битовых флагов в байтовый массив (экономия места) для Arduino 11 | 12 | ### Совместимость 13 | Совместима со всеми Arduino платформами (используются Arduino-функции) 14 | 15 | ## Содержание 16 | - [Инициализация](#init) 17 | - [Использование](#usage) 18 | - [Пример](#example) 19 | - [Версии](#versions) 20 | - [Установка](#install) 21 | - [Баги и обратная связь](#feedback) 22 | 23 | 24 | ## Инициализация 25 | 26 | ```cpp 27 | // указываем количество флагов 28 | BitPack<10> pack; // static буфер внутри 29 | BitPackDyn pack(10); // динамическое выделение 30 | 31 | uint8_t buf[2]; // 1 байт - 8 флагов 32 | BitPackExt pack(buf, 10); // 10 флагов 33 | ``` 34 | 35 | 36 | ## Использование 37 | 38 | ```cpp 39 | // методы 40 | void set(uint16_t num); // установить 41 | void clear(uint16_t num); // сбросить 42 | void toggle(uint16_t num); // переключить 43 | void write(uint16_t num, bool state); // записать 44 | bool read(uint16_t num); // прочитать 45 | void setAll(); // установить все 46 | void clearAll(); // сбросить все 47 | bool copyTo(любой пак); // копировать в 48 | bool copyFrom(любой пак); // копировать из 49 | 50 | uint16_t amount(); // количество флагов 51 | uint16_t size(); // размер pack в байтах 52 | 53 | uint8_t* pack; // доступ к буферу 54 | 55 | // макросы 56 | BP_SET(pack, idx) 57 | BP_CLEAR(pack, idx) 58 | BP_READ(pack, idx) 59 | BP_TOGGLE(pack, idx) 60 | BP_WRITE(pack, idx) 61 | 62 | // настройки (до подключения библиотеки) 63 | #define BP_NO_ARRAY // убрать доступ через [] - экономит 2 байта RAM 64 | ``` 65 | 66 | #### BitPackExt 67 | ```cpp 68 | BitPackExt() {} 69 | 70 | // передать буфер и его размер в количестве флагов (8 флагов - 1 байт) 71 | BitPackExt(uint8_t* pack, uint16_t amount, bool clear = true); 72 | 73 | // передать буфер и его размер в количестве флагов (8 флагов - 1 байт) 74 | void setBuffer(uint8_t* pack, uint16_t amount, bool clear = true); 75 | ``` 76 | 77 | #### BitPackDyn 78 | ```cpp 79 | BitPackDyn() {} 80 | 81 | // указать количество флагов 82 | BitPackDyn(uint16_t amount); 83 | 84 | // указать количество флагов 85 | void init(uint16_t amount); 86 | ``` 87 | 88 | ### Доступ через [] 89 | В библиотеке реализован удобный доступ к битам через образение как к массиву `[]`. Этот способ *чуть медленнее* использования функций set/read/write! 90 | ```cpp 91 | BitPack<10> flags; 92 | flags[0] = 1; 93 | Serial.println(flags[0]); 94 | bool f = flags[0]; 95 | 96 | BitPack<10> flags2; 97 | flags[0] = flags2[0]; 98 | 99 | // примечание: 100 | // такое приравнивание некорректно! Используй copyTo/copyFrom 101 | flags = flags2; 102 | 103 | flags.copyTo(flags2); // копировать весь пакет 104 | ``` 105 | 106 | ### BitFlags 107 | ```cpp 108 | // пакет флагов 109 | T flags = 0; 110 | 111 | // прочитать бит 112 | bool read(const T x); 113 | 114 | // установить биты маской 115 | void set(const T x); 116 | 117 | // очистить биты маской 118 | void clear(const T x); 119 | 120 | // записать бит 121 | void write(const T x, const bool v); 122 | 123 | // получить маску 124 | T mask(const T x); 125 | 126 | // стоят все биты в маске 127 | bool isSet(const T x); 128 | 129 | // очищены все биты в маске 130 | bool isClear(const T x); 131 | 132 | // сравнить маску со значением 133 | bool compare(const T x, const T y); 134 | ``` 135 | 136 | Ещё три пакета фиксированного количества флагов `BitFlags8`, `BitFlags16`, `BitFlags32` на 8/16/32 флагов соответственно. Они работают чуть иначе, как регистры. Можно ставить и читать несколько флагов за одно действие, что сильно повышает производительность. Для удобства можно объявить флаги как биты: 137 | ```cpp 138 | #define MY_FLAG_0 bit(0) 139 | #define KEK_FLAG bit(1) 140 | #define SOME_F bit(2) 141 | 142 | BitFlags8 flags; 143 | flags.set(KEK_FLAG | SOME_F); // установить два флага 144 | if (flags.read(KEK_FLAG | SOME_F)); // проверить два флага 145 | 146 | // операция compare берёт маску по первому аргументу и сравнивает со вторым 147 | // фактически смысл такой: определение ситуации, когда из указанных флагов подняты только определённые 148 | // здесь - из флагов KEK_FLAG и SOME_F поднят только SOME_F (KEK_FLAG опущен) 149 | if (flags.compare(KEK_FLAG | SOME_F, SOME_F)); 150 | ``` 151 | 152 | 153 | ## Пример 154 | Остальные примеры смотри в **examples**! 155 | 156 | ```cpp 157 | #include "BitPack.h" 158 | 159 | // указываем количество флагов 160 | BitPack<10> flags; 161 | 162 | void setup() { 163 | Serial.begin(9600); 164 | flags.clearAll(); // опустить все 165 | flags.set(1); // поднять флаг 166 | flags.set(3); 167 | flags.write(3, 1); 168 | Serial.println(flags.read(0)); // прочитать флаг 169 | Serial.println(flags.read(1)); 170 | Serial.println(flags.read(2)); 171 | 172 | flags[3] = 0; // можно писать через [] 173 | Serial.println(flags[3]); // можно читать через [] 174 | 175 | BitPack<10> flags2; 176 | flags[0] = flags2[1]; // копировать бит 177 | flags.copyTo(flags2); // копировать весь пакет 178 | } 179 | 180 | void loop() { 181 | } 182 | ``` 183 | 184 | 185 | 186 | ## Версии 187 | - v1.0 188 | - v1.1 - пофикшен доступ через [], добавлены новые инструменты 189 | - v1.1.1 - перезалив 190 | - v1.2 - добавлены copy методы, упрощён доступ через массив 191 | - v1.3 - добавлена отдельная инициализация для BitPackExt и BitPackDyn 192 | - v1.3.1 - добавлен copy и move конструктор для BitPackDyn. Добавлены инструменты BitFlags8, BitFlags16, BitFlags32 193 | 194 | 195 | ## Установка 196 | - Библиотеку можно найти по названию **BitPack** и установить через менеджер библиотек в: 197 | - Arduino IDE 198 | - Arduino IDE v2 199 | - PlatformIO 200 | - [Скачать библиотеку](https://github.com/GyverLibs/BitPack/archive/refs/heads/main.zip) .zip архивом для ручной установки: 201 | - Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64) 202 | - Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32) 203 | - Распаковать и положить в *Документы/Arduino/libraries/* 204 | - (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив 205 | - Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 206 | ### Обновление 207 | - Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи 208 | - Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить" 209 | - Вручную: **удалить папку со старой версией**, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам! 210 | 211 | 212 | ## Баги и обратная связь 213 | При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru) 214 | Библиотека открыта для доработки и ваших **Pull Request**'ов! 215 | 216 | При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать: 217 | - Версия библиотеки 218 | - Какой используется МК 219 | - Версия SDK (для ESP) 220 | - Версия Arduino IDE 221 | - Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде 222 | - Какой код загружался, какая работа от него ожидалась и как он работает в реальности 223 | - В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код 224 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | This is an automatic translation, may be incorrect in some places. See sources and examples! 2 | 3 | # Bitpack 4 | Library for packing bit flags in the byte array (saving space) for Arduino 5 | 6 | ## compatibility 7 | Compatible with all arduino platforms (used arduino functions) 8 | 9 | ## Content 10 | - [initialization] (#init) 11 | - [use] (#usage) 12 | - [Example] (# Example) 13 | - [versions] (#varsions) 14 | - [installation] (# Install) 15 | - [bugs and feedback] (#fedback) 16 | 17 | 18 | ## initialization 19 | 20 | `` `CPP 21 | // indicate the number of flags 22 | Bitpack <10> Pack;// static buffer inside 23 | Bitpackdyn Pack (10);// Dynamic discharge 24 | 25 | uint8_t buf [2];// 1 byte - 8 flags 26 | Bitpackext Pack (BUF, 10);// 10 flags 27 | `` ` 28 | 29 | 30 | ## Usage 31 | 32 | `` `CPP 33 | // Methods 34 | VOID set (uint8_t num);// install 35 | Void Clear (Uint8_t Num);// reset 36 | VOID TOGGLE (UINT8_T NUM);// switch 37 | VOID Write (Uint8_t Num, Bool State);// Record 38 | Bool Read (uint8_t num);// Read 39 | VOID setall ();// install everything 40 | VOID CLEARALL ();// throw everything 41 | uint16_t amount ();// number of flags 42 | uint16_t size ();// Pack size in bytes 43 | 44 | uint8_t* pack;// access to the buffer 45 | 46 | // Macro 47 | BP_SET (PACK, IDX) 48 | BP_Clear (Pack, IDX) 49 | Bp_read (Pack, IDX) 50 | BP_TOGGLE (PACK, IDX) 51 | BP_WRITE (PACK, IDX) 52 | 53 | // Settings (before connecting the library) 54 | #define bp_no_arry // Remove access through [] - saves 2 bytes RAM 55 | `` ` 56 | 57 | 58 | ## Example 59 | The rest of the examples look at ** Examples **! 60 | 61 | `` `CPP 62 | #include "Bitpack.h" 63 | 64 | // indicate the number of flags 65 | Bitpack <10> Flags; 66 | 67 | VOID setup () { 68 | Serial.Begin (9600); 69 | Flags.clerall ();// lower everything 70 | Flags.Set (1);// raise the flag 71 | Flags.Set (3); 72 | Flags.write (3, 1); 73 | Serial.println (Flags.read (0));// Read the flag 74 | Serial.println (Flags.read (1)); 75 | Serial.println (Flags.read (2)); 76 | 77 | Flags [3] = 0;// can be written through [] 78 | Serial.println (Flags [3]);// can be read through [] 79 | } 80 | 81 | VOID loop () { 82 | } 83 | `` ` 84 | 85 | 86 | 87 | ## versions 88 | - V1.0 89 | - v1.1 - access for [], new tools have been added 90 | - V1.1.1 - REB 91 | 92 | 93 | ## Installation 94 | - The library can be found by the name ** bitpack ** and installed through the library manager in: 95 | - Arduino ide 96 | - Arduino ide v2 97 | - Platformio 98 | - [download the library] (https://github.com/gyverlibs/bitpack/archive/refs/heads/main.zip). Zip archive for manual installation: 99 | - unpack and put in * C: \ Program Files (X86) \ Arduino \ Libraries * (Windows X64) 100 | - unpack and put in * C: \ Program Files \ Arduino \ Libraries * (Windows X32) 101 | - unpack and put in *documents/arduino/libraries/ * 102 | - (Arduino id) Automatic installation from. Zip: * sketch/connect the library/add .Zip library ... * and specify downloaded archive 103 | - Read more detailed instructions for installing libraries [here] (https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%BD%D0%BE%BE%BE%BED0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 104 | ### Update 105 | - I recommend always updating the library: errors and bugs are corrected in the new versions, as well as optimization and new features are added 106 | - Through the IDE library manager:Find the library how to install and click "update" 107 | - Manually: ** remove the folder with the old version **, and then put a new one in its place.“Replacement” cannot be done: sometimes in new versions, files that remain when replacing are deleted and can lead to errors! 108 | 109 | 110 | ## bugs and feedback 111 | Create ** Issue ** when you find the bugs, and better immediately write to the mail [alex@alexgyver.ru] (mailto: alex@alexgyver.ru) 112 | The library is open for refinement and your ** pull Request ** 'ow! 113 | 114 | When reporting about bugs or incorrect work of the library, it is necessary to indicate: 115 | - The version of the library 116 | - What is MK used 117 | - SDK version (for ESP) 118 | - version of Arduino ide 119 | - whether the built -in examples work correctly, in which the functions and designs are used, leading to a bug in your code 120 | - what code has been loaded, what work was expected from it and how it works in reality 121 | - Ideally, attach the minimum code in which the bug is observed.Not a canvas of a thousand lines, but a minimum code -------------------------------------------------------------------------------- /examples/flags/flags.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MY_FLAG_0 bit(0) 5 | #define KEK_FLAG bit(1) 6 | #define SOME_F bit(2) 7 | 8 | enum class Flags { 9 | f1 = bit(0), 10 | f2 = bit(1), 11 | f3 = bit(2), 12 | }; 13 | 14 | void setup() { 15 | Serial.begin(115200); 16 | { 17 | BitFlags8 f; 18 | f.set(Flags::f1); 19 | f.set(Flags::f2); 20 | 21 | Serial.println(f.read(Flags::f1)); 22 | Serial.println(f.read(Flags::f2)); 23 | Serial.println(f.read(Flags::f3)); 24 | } 25 | { 26 | BitFlags8 flags; 27 | flags.set(KEK_FLAG | SOME_F); // установить два флага 28 | Serial.println(flags.read(KEK_FLAG | SOME_F)); // стоит один из флагов 29 | Serial.println(flags.isSet(KEK_FLAG | SOME_F)); // стоят все флаги 30 | 31 | // операция compare берёт маску по первому аргументу и сравнивает со вторым 32 | // фактически смысл такой: определение ситуации, когда из указанных флагов подняты только определённые 33 | // здесь - из флагов KEK_FLAG и SOME_F поднят только SOME_F (KEK_FLAG опущен) 34 | Serial.println(flags.compare(KEK_FLAG | SOME_F, SOME_F)); 35 | } 36 | } 37 | 38 | void loop() { 39 | } -------------------------------------------------------------------------------- /examples/test/test.ino: -------------------------------------------------------------------------------- 1 | #include "BitPack.h" 2 | 3 | // указываем количество флагов 4 | BitPack<10> flags; 5 | 6 | void setup() { 7 | Serial.begin(9600); 8 | flags.clearAll(); // опустить все 9 | flags.set(1); // поднять флаг 10 | flags.set(3); 11 | flags.write(3, 1); 12 | Serial.println(flags.read(0)); // прочитать флаг 13 | Serial.println(flags.read(1)); 14 | Serial.println(flags.read(2)); 15 | flags[3] = 0; // можно писать через [] 16 | Serial.println(flags[3]); // можно читать через [] 17 | } 18 | 19 | void loop() { 20 | } -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For BitPack 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | BitPack KEYWORD1 10 | BitPackExt KEYWORD1 11 | BitPackDyn KEYWORD1 12 | BitFlags8 KEYWORD1 13 | BitFlags16 KEYWORD1 14 | BitFlags32 KEYWORD1 15 | 16 | ####################################### 17 | # Methods and Functions (KEYWORD2) 18 | ####################################### 19 | 20 | set KEYWORD2 21 | clear KEYWORD2 22 | toggle KEYWORD2 23 | write KEYWORD2 24 | read KEYWORD2 25 | setAll KEYWORD2 26 | clearAll KEYWORD2 27 | size KEYWORD2 28 | amount KEYWORD2 29 | copyTo KEYWORD2 30 | copyFrom KEYWORD2 31 | init KEYWORD2 32 | setBuffer KEYWORD2 33 | mask KEYWORD2 34 | compare KEYWORD2 35 | 36 | BP_BYTE KEYWORD2 37 | BP_BIT KEYWORD2 38 | BP_SET KEYWORD2 39 | BP_CLEAR KEYWORD2 40 | BP_READ KEYWORD2 41 | BP_TOGGLE KEYWORD2 42 | BP_WRITE KEYWORD2 43 | 44 | ####################################### 45 | # Constants (LITERAL1) 46 | ####################################### 47 | 48 | BP_NO_ARRAY LITERAL1 -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=BitPack 2 | version=1.3.5 3 | author=AlexGyver 4 | maintainer=AlexGyver 5 | sentence=Library for packing bit flags into byte array 6 | paragraph=Library for packing bit flags into byte array 7 | category=Data Processing 8 | url=https://github.com/GyverLibs/BitPack 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/BitFlags.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // ================= BIT FLAGS ================= 5 | template 6 | struct BitFlags { 7 | // пакет флагов 8 | T flags = 0; 9 | 10 | // прочитать бит 11 | template 12 | inline bool read(const T1 x) const { 13 | return flags & (T)x; 14 | } 15 | 16 | // установить биты маской 17 | template 18 | inline void set(const T1 x) { 19 | flags |= (T)x; 20 | } 21 | 22 | // очистить биты маской 23 | template 24 | inline void clear(const T1 x) { 25 | flags &= ~((T)x); 26 | } 27 | 28 | // записать бит 29 | template 30 | inline void write(const T1 x, const bool v) { 31 | v ? set(x) : clear(x); 32 | } 33 | 34 | // получить маску 35 | template 36 | inline T mask(const T1 x) const { 37 | return flags & (T)x; 38 | } 39 | 40 | // стоят все биты в маске 41 | template 42 | inline bool isSet(const T1 x) const { 43 | return (flags & (T)x) == (T)x; 44 | } 45 | 46 | // очищены все биты в маске 47 | template 48 | inline bool isClear(const T1 x) const { 49 | return !(flags & (T)x); 50 | } 51 | 52 | // сравнить маску со значением 53 | template 54 | inline bool compare(const T1 x, const T2 y) const { 55 | return (flags & (T)x) == (T)y; 56 | } 57 | }; 58 | 59 | struct BitFlags8 : public BitFlags {}; 60 | struct BitFlags16 : public BitFlags {}; 61 | struct BitFlags32 : public BitFlags {}; -------------------------------------------------------------------------------- /src/BitPack.h: -------------------------------------------------------------------------------- 1 | /* 2 | BitPack - библиотека для упаковки битовых флагов в байтовый массив (экономия места) 3 | Документация: 4 | GitHub: https://github.com/GyverLibs/BitPack 5 | 6 | AlexGyver, alex@alexgyver.ru 7 | https://alexgyver.ru/ 8 | MIT License 9 | */ 10 | 11 | #pragma once 12 | #include 13 | #include "BitFlags.h" 14 | 15 | #define BP_BYTE(pack, idx) pack[(idx) >> 3] 16 | #define BP_BIT(pack, idx) ((idx) & 0b111) 17 | #define BP_SET(pack, idx) (BP_BYTE(pack, idx) |= 1 << BP_BIT(pack, idx)) 18 | #define BP_CLEAR(pack, idx) (BP_BYTE(pack, idx) &= ~(1 << BP_BIT(pack, idx))) 19 | #define BP_READ(pack, idx) ((BP_BYTE(pack, idx) >> BP_BIT(pack, idx)) & 1) 20 | #define BP_TOGGLE(pack, idx) (BP_BYTE(pack, idx) ^= 1 << BP_BIT(pack, idx)) 21 | #define BP_WRITE(pack, idx, val) (val) ? BP_SET(pack, idx) : BP_CLEAR(pack, idx) 22 | 23 | // ============== STATIC PACK ============== 24 | template 25 | class BitPack { 26 | public: 27 | uint8_t pack[(flag_amount + 8 - 1) >> 3]; // round up 28 | 29 | BitPack() { 30 | clearAll(); 31 | } 32 | 33 | // размер pack в байтах 34 | uint16_t size() const { 35 | return (flag_amount + 8 - 1) >> 3; 36 | } 37 | 38 | // количество флагов 39 | uint16_t amount() const { 40 | return flag_amount; 41 | } 42 | 43 | // установить 44 | void set(uint16_t idx) { 45 | if (idx < flag_amount) BP_SET(pack, idx); 46 | } 47 | 48 | // снять 49 | void clear(uint16_t idx) { 50 | if (idx < flag_amount) BP_CLEAR(pack, idx); 51 | } 52 | 53 | // инвертировать 54 | void toggle(uint16_t idx) { 55 | if (idx < flag_amount) BP_TOGGLE(pack, idx); 56 | } 57 | 58 | // записать 59 | void write(uint16_t idx, bool state) { 60 | if (idx < flag_amount) BP_WRITE(pack, idx, state); 61 | } 62 | 63 | // прочитать 64 | bool read(uint16_t idx) const { 65 | if (idx < flag_amount) return BP_READ(pack, idx); 66 | else return 0; 67 | } 68 | 69 | // установить все 70 | void setAll() { 71 | memset(pack, 255, size()); 72 | } 73 | 74 | // очистить все 75 | void clearAll() { 76 | memset(pack, 0, size()); 77 | } 78 | 79 | // копировать в 80 | bool copyTo(BitPack& bp) { 81 | if (amount() != bp.amount()) return 0; 82 | memcpy(bp.pack, pack, size()); 83 | return 1; 84 | } 85 | 86 | // копировать из 87 | bool copyFrom(BitPack& bp) { 88 | if (amount() != bp.amount()) return 0; 89 | memcpy(pack, bp.pack, size()); 90 | return 1; 91 | } 92 | 93 | #ifndef BP_NO_ARRAY 94 | BitPack& operator[](uint16_t idx) { 95 | _idx = idx; 96 | return *this; 97 | } 98 | void operator=(bool val) { 99 | write(_idx, val); 100 | } 101 | operator bool() const { 102 | return read(_idx); 103 | } 104 | void operator=(BitPack& bp) { 105 | write(_idx, (bool)bp); 106 | } 107 | #endif 108 | 109 | private: 110 | #ifndef BP_NO_ARRAY 111 | uint16_t _idx; 112 | #endif 113 | }; 114 | 115 | // ============== EXTERNAL BUFFER ============== 116 | class BitPackExt { 117 | public: 118 | uint8_t* pack = nullptr; 119 | 120 | BitPackExt() {} 121 | 122 | // передать буфер и его размер в количестве флагов (8 флагов - 1 байт) 123 | BitPackExt(uint8_t* pack, uint16_t amount, bool clear = true) { 124 | setBuffer(pack, amount, clear); 125 | } 126 | 127 | // передать буфер и его размер в количестве флагов (8 флагов - 1 байт) 128 | void setBuffer(uint8_t* pack, uint16_t amount, bool clear = true) { 129 | this->pack = pack; 130 | this->_amount = amount; 131 | if (clear) clearAll(); 132 | } 133 | 134 | // размер pack в байтах 135 | uint16_t size() const { 136 | return (_amount + 8 - 1) >> 3; // round up 137 | } 138 | 139 | // количество флагов 140 | uint16_t amount() const { 141 | return _amount; 142 | } 143 | 144 | // установить 145 | void set(uint16_t idx) { 146 | if (pack && idx < _amount) BP_SET(pack, idx); 147 | } 148 | 149 | // снять 150 | void clear(uint16_t idx) { 151 | if (pack && idx < _amount) BP_CLEAR(pack, idx); 152 | } 153 | 154 | // инвертировать 155 | void toggle(uint16_t idx) { 156 | if (pack && idx < _amount) BP_TOGGLE(pack, idx); 157 | } 158 | 159 | // записать 160 | void write(uint16_t idx, bool state) { 161 | if (pack && idx < _amount) BP_WRITE(pack, idx, state); 162 | } 163 | 164 | // прочитать 165 | bool read(uint16_t idx) const { 166 | if (pack && idx < _amount) return BP_READ(pack, idx); 167 | else return 0; 168 | } 169 | 170 | // установить все 171 | void setAll() { 172 | if (pack) memset(pack, 255, size()); 173 | } 174 | 175 | // очистить все 176 | void clearAll() { 177 | if (pack) memset(pack, 0, size()); 178 | } 179 | 180 | // копировать в 181 | bool copyTo(BitPackExt& bp) { 182 | if (!pack || amount() != bp.amount()) return 0; 183 | memcpy(bp.pack, pack, size()); 184 | return 1; 185 | } 186 | 187 | // копировать из 188 | bool copyFrom(BitPackExt& bp) { 189 | if (!pack || amount() != bp.amount()) return 0; 190 | memcpy(pack, bp.pack, size()); 191 | return 1; 192 | } 193 | 194 | #ifndef BP_NO_ARRAY 195 | BitPackExt& operator[](uint16_t idx) { 196 | _idx = idx; 197 | return *this; 198 | } 199 | void operator=(bool val) { 200 | write(_idx, val); 201 | } 202 | operator bool() const { 203 | return read(_idx); 204 | } 205 | void operator=(BitPackExt& bp) { 206 | write(_idx, (bool)bp); 207 | } 208 | #endif 209 | 210 | protected: 211 | uint16_t _amount; 212 | 213 | private: 214 | #ifndef BP_NO_ARRAY 215 | uint16_t _idx; 216 | #endif 217 | }; 218 | 219 | // ============== DYNAMIC BUFFER ============== 220 | class BitPackDyn : public BitPackExt { 221 | public: 222 | BitPackDyn() {} 223 | 224 | // указать количество флагов 225 | BitPackDyn(uint16_t amount) { 226 | init(amount); 227 | } 228 | 229 | BitPackDyn(const BitPackDyn& val) { 230 | copy(val); 231 | } 232 | void operator=(const BitPackDyn& val) { 233 | copy(val); 234 | } 235 | 236 | #if __cplusplus >= 201103L 237 | BitPackDyn(BitPackExt&&) = delete; 238 | BitPackDyn& operator=(BitPackExt&&) = delete; 239 | 240 | BitPackDyn(BitPackDyn&& rval) noexcept { 241 | move(rval); 242 | } 243 | void operator=(BitPackDyn&& rval) noexcept { 244 | move(rval); 245 | } 246 | #endif 247 | 248 | ~BitPackDyn() { 249 | delete[] pack; 250 | } 251 | 252 | // указать количество флагов 253 | void init(uint16_t amount) { 254 | delete[] pack; 255 | _amount = amount; // need for size() 256 | pack = new uint8_t[size()]; 257 | if (!pack) _amount = 0; 258 | clearAll(); 259 | } 260 | 261 | // удалить буфер 262 | void reset() { 263 | delete[] pack; 264 | pack = nullptr; 265 | _amount = 0; 266 | } 267 | 268 | // копировать из 269 | void copy(const BitPackDyn& val) { 270 | if (this == &val || pack == val.pack) return; 271 | if (!val.pack) { 272 | reset(); 273 | return; 274 | } 275 | memcpy(pack, val.pack, val.size()); 276 | _amount = val._amount; 277 | } 278 | 279 | // переместить из 280 | void move(BitPackDyn& rval) noexcept { 281 | delete[] pack; 282 | pack = rval.pack; 283 | _amount = rval._amount; 284 | rval.pack = nullptr; 285 | } 286 | }; --------------------------------------------------------------------------------