UdonLibrary 1.0.0
機械システム研究部 C++ ライブラリ
読み取り中…
検索中…
一致する文字列を見つけられません
BitPack.hpp
[詳解]
1#pragma once
2
4#include <type_traits>
5#include <iterator>
6#include <vector>
7
8#include "Bit.hpp"
9#include "Math.hpp"
10
11namespace Udon
12{
13
22 template <typename InputIterator, typename Functor>
23 void BitPack(const InputIterator begin, const InputIterator end, Functor callback)
24 {
25 static_assert(std::is_same<typename std::iterator_traits<InputIterator>::value_type, uint8_t>::value, "container element type must be uint8_t");
26 static_assert(std::is_same<typename std::result_of<Functor(uint8_t)>::type, void>::value, "callback function must be void(uint8_t)");
27
28 uint8_t extracteMsb = 0; // 各要素のMSB(最上位ビット)から抽出された分のデータ
29 uint8_t extracteCount = 0; // extracteMsbに格納されたデータのビット数
30
31 bool isFirst = true;
32
33 for (auto it = begin; it != end; ++it)
34 {
35 BitWrite(extracteMsb, extracteCount, BitRead(*it, 7)); // MSBを抽出してextracteMsbに格納する
36
37 if (isFirst)
38 {
39 callback(*it | 0b10000000); // 先頭のデータはMSBが1
40 }
41 else
42 {
43 isFirst = false;
44 callback(*it & 0b01111111); // MSBを除いたデータをコールバック関数に渡す
45 }
46
47 if (++extracteCount >= 7)
48 {
49 extracteCount = 0;
50 callback(extracteMsb);
51 extracteMsb = {};
52 }
53 }
54
55 if (extracteCount) // extracteMsbにデータが残っていれば追加で渡す
56 {
57 callback(extracteMsb);
58 }
59 }
60
69 template <typename OutputIterator, typename Functor>
70 bool BitUnpack(OutputIterator begin, OutputIterator end, Functor callback)
71 {
72 static_assert(std::is_same<typename std::iterator_traits<OutputIterator>::value_type, uint8_t>::value, "container element type must be uint8_t");
73 static_assert(std::is_same<typename std::result_of<Functor()>::type, uint8_t>::value, "callback function must be uint8_t()");
74
75 uint8_t extracteCount = 0; // 通常MSBなしデータの取得数
76
77 bool isFirst = true;
78
79 for (auto it = begin; it != end;)
80 {
81 const auto data = callback();
82
83 // バイト列の先頭のMSBは必ず 1
84 if (isFirst && not(data & 0b10000000))
85 {
86 return false;
87 }
88 else
89 {
90 isFirst = false;
91 }
92
93 *it = data;
94 ++it;
95 ++extracteCount;
96
97 if (extracteCount == 7) // 7バイトごとにMSBの集合が来る
98 {
99 extracteCount = 0;
100
101 const uint8_t msb = callback();
102
103 auto c = it;
104
105 for (int i = 0; i < 7; ++i)
106 {
107 --c; // c は最初、MSBの集合を指しているので、先に1バイト戻す
108 BitWrite(*c, 7, BitRead(msb, 7 - 1 /*MSB bit*/ - i)); // 各要素のMSBを復元
109 }
110 }
111 }
112
113 if (extracteCount) // パック時 extracteMsb にデータが残っている場合、追加でデータが渡されるのでそれを処理する
114 {
115 const uint8_t msb = callback();
116
117 auto c = end;
118
119 for (int i = 0; i < extracteCount; ++i)
120 {
121 --c; // end は領域を持たないので、先に1バイト戻す
122 BitWrite(*(c), 7, BitRead(msb, extracteCount - 1 /*MSB bit*/ - i)); // 各要素の要素のMSBを復元
123 }
124 }
125
126 return true;
127 }
128
132 inline constexpr size_t BitPackedSize(size_t size)
133 {
134 return (size_t)Udon::Ceil(size * 8 / 7.0); // 切り上げ
135 }
136
140 inline constexpr size_t BitUnpackedSize(size_t size)
141 {
142 return size * 7 / 8; // 切り捨て
143 }
144
148 inline std::vector<uint8_t> BitPack(const std::vector<uint8_t>& data)
149 {
150 std::vector<uint8_t> result(BitPackedSize(data.size()));
151
152 auto it = result.begin();
153
154 BitPack(data.begin(), data.end(), [&it](uint8_t data)
155 { *it++ = data; });
156
157 return result;
158 }
159
160 inline std::vector<uint8_t> BitUnpack(const std::vector<uint8_t>& data)
161 {
162 std::vector<uint8_t> result(BitUnpackedSize(data.size()));
163
164 auto it = data.begin();
165
166 BitUnpack(result.begin(), result.end(), [&it]() -> uint8_t
167 { return *it++; });
168
169 return result;
170 }
171
172} // namespace Udon
Definition Bit.hpp:12
void BitWrite(Ty &rhs, uint8_t bit, bool value)
特定のビットに値を書き込む
Definition Bit.hpp:61
void BitPack(const InputIterator begin, const InputIterator end, Functor callback)
バイト列のMSB(最上位ビット)を抽出し、7bitごとに分割してコールバック関数に渡す
Definition BitPack.hpp:23
bool BitUnpack(OutputIterator begin, OutputIterator end, Functor callback)
7bit分割されたデータを結合する
Definition BitPack.hpp:70
constexpr size_t BitPackedSize(size_t size)
ビットパックされたデータのサイズを取得する
Definition BitPack.hpp:132
constexpr size_t BitUnpackedSize(size_t size)
ビットアンパックされたデータのサイズを取得する
Definition BitPack.hpp:140
constexpr int Ceil(double x)
小数点切り上げ (std::ceil)
Definition Math.hpp:129
bool BitRead(const Ty &rhs, uint8_t bit)
特定のビットを読み取る
Definition Bit.hpp:20