Skip to content

Commit 598a5d9

Browse files
lgritzscott-wilson
authored andcommitted
fmath.h: add span-based bit_unpack() utility (AcademySoftwareFoundation#4723)
This also fixes a sonar warning about being unsure of a raw pointer was used out of range. Signed-off-by: Larry Gritz <[email protected]> Signed-off-by: Scott Wilson <[email protected]>
1 parent cdc641e commit 598a5d9

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

src/include/OpenImageIO/fmath.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,18 +1133,20 @@ bit_pack(cspan<T> data, void* out, int outbits)
11331133
/// will be stored in a successive out[i].
11341134
template<typename T>
11351135
inline void
1136-
bit_unpack(int n, const unsigned char* in, int inbits, T* out)
1136+
bit_unpack(cspan<unsigned char> in, int inbits, span<T> out)
11371137
{
11381138
static_assert(std::is_same<T,uint8_t>::value ||
11391139
std::is_same<T,uint16_t>::value ||
11401140
std::is_same<T,uint32_t>::value,
11411141
"bit_unpack must be unsigned int 8/16/32");
1142+
OIIO_DASSERT(in.size() * 8 >= inbits * out.size());
11421143
OIIO_DASSERT(inbits >= 1 && inbits < 32); // surely bugs if not
11431144
// int highest = (1 << inbits) - 1;
1145+
size_t n = out.size();
11441146
int B = 0, b = 0;
11451147
// Invariant:
11461148
// So far, we have used in[0..B-1] and the high b bits of in[B].
1147-
for (int i = 0; i < n; ++i) {
1149+
for (size_t i = 0; i < n; ++i) {
11481150
long long val = 0;
11491151
int valbits = 0; // bits so far we've accumulated in val
11501152
while (valbits < inbits) {
@@ -1179,6 +1181,23 @@ bit_unpack(int n, const unsigned char* in, int inbits, T* out)
11791181

11801182

11811183

1184+
/// Decode n packed inbits-bits values from in[...] into normal uint8,
1185+
/// uint16, or uint32 representation of `T out[0..n-1]`. In other words,
1186+
/// each successive `inbits` of `in` (allowing spanning of byte boundaries)
1187+
/// will be stored in a successive out[i].
1188+
/// Note that this is the "unsafe" raw pointer version, and we recommend
1189+
/// instead using the span-based version.
1190+
template<typename T>
1191+
OIIO_DEPRECATED("Use span-based version")
1192+
inline void
1193+
bit_unpack(int n, const unsigned char* in, int inbits, T* out)
1194+
{
1195+
return bit_unpack(cspan<unsigned char>(in, (n * inbits + 7) / 8),
1196+
inbits, span<T>(out, n));
1197+
}
1198+
1199+
1200+
11821201
/// A DataProxy<I,E> looks like an (E &), but it really holds an (I &)
11831202
/// and does conversions (via convert_type) as it reads in and out.
11841203
/// (I and E are for INTERNAL and EXTERNAL data types, respectively).

src/libutil/fmath_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ test_packbits()
449449
" packed to 10 bits, as 16 bit values: %04x %04x %04x %04x %04x\n",
450450
u10[0], u10[1], u10[2], u10[3], u10[4]);
451451
uint16_t u16[8];
452-
bit_unpack(8, (const unsigned char*)u10, 10, u16);
452+
bit_unpack(make_cspan((const unsigned char*)u10, 10), 10, make_span(u16));
453453
Strutil::printf(
454454
" unpacked back to 16 bits: %04x %04x %04x %04x %04x %04x %04x %04x\n",
455455
u16[0], u16[1], u16[2], u16[3], u16[4], u16[5], u16[6], u16[7]);

0 commit comments

Comments
 (0)