Russian Qt Forum
Ноябрь 25, 2024, 09:04 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 3 [4]   Вниз
  Печать  
Автор Тема: чтение и запись битовых структур данных  (Прочитано 21126 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #45 : Май 09, 2021, 11:25 »

потому что на адрес нельзя закладываться
Да, посмотрел старый код, там у мапы есть еще функтор
Код
C++ (Qt)
bool СompareTypeInfo( const std::type_info * t0, const std::type_info * t1 )
{
 return t0->before(*t1);
}
Т.е. можно и так, хотя type_index явно удобнее
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #46 : Май 09, 2021, 23:35 »

Цитировать
Кстати для статики почему бы не задействовать простецкие bitfield (от которых Вы гордо отказались)
не очень понял как ваш пример мне поможет в случае, когда последнее поле не влезает в границу uint32 или uint64 (например, для uint32 индекс 30 и размер 5), или если структура больше 64 бит. как читать CFlag — тоже непонятно (fread? >>? проблемы с endianness опустим), плюс придется самому считать размеры таких полей чтоб все влезло (опять же, ненужная ручная работа). прошу продемонстрировать ©

если предполагается писать в m_value, а читать из битовых полей, то в С++ остается только верить, что компилятор сделает как ожидается, но давайте писать код, следующий стандарту Улыбающийся Либо надо писать парсер на С, где такой трюк абсолютно законен.
Цитировать
И для мапы - только m_value
связь с мапой не уловил
Цитировать
Ну а зачем иметь/заводить 2 представления данных ? Я бы этого всячески избегал
с сырыми данными в моем случае крайне неудобно работать, их надо преобразовывать в более подходящие для «пользовательского» кода структуры.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #47 : Май 10, 2021, 10:24 »

опять же, ненужная ручная работа
Может быть. Но гонять (большие) структуры сырые<->рабочие - мало не покажется, считаю оно того стоит.

не очень понял как ваш пример мне поможет в случае, когда последнее поле не влезает в границу uint32 или uint64 (например, для uint32 индекс 30 и размер 5), или если структура больше 64 бит. как читать CFlag — тоже непонятно (fread? >>? проблемы с endianness опустим), плюс придется самому считать размеры таких полей чтоб все влезло (опять же, ненужная ручная работа). прошу продемонстрировать ©

если предполагается писать в m_value, а читать из битовых полей, то в С++ остается только верить, что компилятор сделает как ожидается, но давайте писать код, следующий стандарту Улыбающийся Либо надо писать парсер на С, где такой трюк абсолютно законен.
Чтение/запись получает адрес и число бит (не байт) которое берется из мапы. Стандартные операторы >> здесь применить не выйдет т.к. в одном байте могут сидеть части 2 структур.  Для bitfield я бы делал так

1) ограничил вместимость CFlag 32 битами. Если битовое поле >= инта, то почти наверняка компилятор как-то будет его равнять, и непрерывный битовый массив мы не получим, связываться с этим не стоит. Это нормально, делать большие члены битовыми неразумно.

2) Сделал бы последним членом подставу, напр m_padding, так чтобы сумма размеров = 32. Да, его размер придется вычислять руками, есть такая "шероховатость"  Улыбающийся

Ну и считаем число бит
Код
C++ (Qt)
template<class CFlag>
int CalcFlagBits( void )
{
 static_assert(sizeof(CFlag) == sizeof(unit32));
 CFlag flag;
 flag.m_value = (uint32) -1;
 flag.m_padding = 0;
 return ffs(flag.m_value);   // по-моему эта ф-ция считает число единичек, могу путать
}

Интереснее как писать более продвинутые члены, напр контейнеры
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #48 : Май 10, 2021, 11:16 »

Может быть. Но гонять (большие) структуры сырые<->рабочие - мало не покажется, считаю оно того стоит.


Это называется "абстракция". Завтра вам надо другой формат поддерживать - удачи менять все структуры.
На самом деле такие "битовые" операции даже в моей текущей области (спутники) нужны (правда тут тупо кодом все читается, без декларативных структур) и вот у вас условно 10 похожих но разных форматов расположения битовых полей. Условно идет Хедер1 по которому мы понимаем идет ли дальше Хедер2А или Хедер2Б. В итоге всё это льется в огромный объект с кучей свойств - в зависимости от какие-то свойства есть, каких-то нет. Причем одни и те же свойства в разных вариантах на разной битовой позиции, ох я бы не хотел работать с битовыми структурами напрямую
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #49 : Май 10, 2021, 12:16 »

Это называется "абстракция". Завтра вам надо другой формат поддерживать - удачи менять все структуры.
Не понял что Вы хотели сказать Улыбающийся Лично я считаю что данные должны существовать только в одном виде/экземпляре, а побитовый I/O - всего лишь один из вариантов (де)сериализации. Поэтому вариант с BitField<> (создание массивных структур чисто для I/O) осуждаю (ну осуждать много ума не надо  Улыбающийся)

Тут вот какая мысля. Для пачки битовых полей считаем размер автоматом. Так может и для др полей тоже? Чтобы избавиться от утомительной "регистрации" и заполнять мапу автоматом.
« Последнее редактирование: Май 10, 2021, 12:20 от Igors » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #50 : Май 10, 2021, 13:32 »

Цитировать
Чтение/запись получает адрес и число бит (не байт) которое берется из мапы
то есть теперь эти оффсеты надо вычислять самому для заполнения мапы (да, делается один раз, но...), а не просто пользоваться руководством по требуемому битовому формату. а сколько будет веселья, если надо будет чуть-чуть их поменять, а они не влезут в вычисленные нами границы байт... Улыбающийся
Цитировать
в одном байте могут сидеть части 2 структур
все для людей!
Цитировать
Если битовое поле >= инта, то почти наверняка компилятор как-то будет его равнять, и непрерывный битовый массив мы не получим, связываться с этим не стоит. Это нормально, делать большие члены битовыми неразумно.
нет, я решительно не хочу думать что там компилятор выравнивает и куда, я хочу решать свою прикладную задачу — просто напишу BitField<34>.
Цитировать
Сделал бы последним членом подставу, напр m_padding
еще и паддинг самому считать... Улыбающийся
Цитировать
Ну и считаем число бит
вообще не понял что эта функция делает. при чем там -1 и число единиц?
Цитировать
Интереснее как писать более продвинутые члены, напр контейнеры
просто читаем элементы подряд. но тут темплейты, такой код слишком простой плохой Улыбающийся
Код
C++ (Qt)
template<std::size_t Size, BitFieldSizeType Bits>
struct BitArray
{
 std::array<BitField<Bits>, Size> arr;
 
 auto parse(gsl::span<uint8_t> const& sp, uint64_t& offset)
 {
   for (auto& el : arr)
     el.parse(sp, offset);
   return arr;
 }
};
конечно, каждому контейнеру надо будет писать свою реализацию. но тут можно блеснуть словом «концепт», сказав, что мы поддерживаем любую структуру данных, которая имеет метод auto parse(gsl::span<uint8_t> const& sp, uint64_t& offset). (кстати, на эту же тему недавно нашел нечто похожее на протоколы из objc/swift: https://github.com/ldionne/dyno)
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #51 : Май 10, 2021, 14:36 »

то есть теперь эти оффсеты надо вычислять самому для заполнения мапы (да, делается один раз, но...), а не просто пользоваться руководством по требуемому битовому формату.
Такое "руководство" по-любому будет, только я предлагаю написать его как создание мапы, а не создавать новые типы, а потом еще перегонять данные.

а сколько будет веселья, если надо будет чуть-чуть их поменять, а они не влезут в вычисленные нами границы байт... Улыбающийся
Да, придется  немного подсуетиться. Но гораздо вероятнее вариант "изменилось но еще влезает" - и мне ничего делать не надо, а Вам...

еще и паддинг самому считать... Улыбающийся
Никто не заставляет, можно тупенько почленно, просто заманчиво резко сократить число строк "руководства".

просто напишу BitField<34>.
Да, отказаться от уже написанного кода непросто  Улыбающийся
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #52 : Май 10, 2021, 15:47 »

у меня нет никакого «написанного» кода, есть пока лишь пара тестовых примеров. но ваш подход кажется чрезмерно переусложненным по сравнению с декларативным темплейтным. демонстрации аналога http://www.prog.org.ru/index.php?topic=33021.msg244833#msg244833 также не последовало.

дальнейший спор считаю бессмысленным, победила дружба Улыбающийся
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #53 : Май 11, 2021, 07:21 »

у меня нет никакого «написанного» кода, есть пока лишь пара тестовых примеров. но ваш подход кажется чрезмерно переусложненным по сравнению ..
Возможно Вы "по инерции" считаете что есть "сырые" и "рабочие" данные, но я предлагаю иметь только рабочие. Сравним 2 варианта
Код:
struct BasicBitItem
{
  BitField<16> header;
...
Код:
BasicBitItem item;

  SetBitsCount(item, item.header, 16);
...
"Расходы по написанию" одинаковы. Контроль ошибок тот же. Если нужен "битовый размер поля" - то почему его не создать самым простым способом (мапой)? Зачем городить немалые структуры только для I/O, а потом еще перегружать данные туда-сюда? 

Правда возможно что "битовый размер" - еще не все что нужно I/O. Вполне вероятно что читаются/пишутся поля которых нет в рабочих данных, и наоборот. И в моем варианте неясно как уложить такие в "руководство". Ну проблема их заполнения все равно остается. Но это уже чисто мои догадки  Улыбающийся

дальнейший спор считаю бессмысленным, победила дружба Улыбающийся
Согласен  Улыбающийся
Записан
Страниц: 1 2 3 [4]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.227 секунд. Запросов: 23.