Skip to content

various byteSwap and bit_cast cleanups #3227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions src/asfvideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,11 @@ bool AsfVideo::GUIDTag::operator==(const AsfVideo::GUIDTag& other) const {
}

AsfVideo::GUIDTag::GUIDTag(const uint8_t* bytes) {
std::memcpy(&data1_, bytes, DWORD);
std::memcpy(&data2_, bytes + DWORD, WORD);
std::memcpy(&data3_, bytes + DWORD + WORD, WORD);
data1_ = (static_cast<uint32_t>(bytes[3]) << 24) | (static_cast<uint32_t>(bytes[2]) << 16) |
(static_cast<uint32_t>(bytes[1]) << 8) | (static_cast<uint32_t>(bytes[0]));
data2_ = (static_cast<uint16_t>(bytes[5]) << 8) | (static_cast<uint16_t>(bytes[4]));
data3_ = (static_cast<uint16_t>(bytes[7]) << 8) | (static_cast<uint16_t>(bytes[6]));
std::copy(bytes + QWORD, bytes + (2 * QWORD), data4_.begin());
if (isBigEndianPlatform()) {
data1_ = byteSwap(data1_, true);
data2_ = byteSwap(data2_, true);
data3_ = byteSwap(data3_, true);
}
}

std::string AsfVideo::GUIDTag::to_string() const {
Expand Down
19 changes: 10 additions & 9 deletions src/bmffimage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,16 @@ BmffImage::BmffImage(BasicIo::UniquePtr io, bool /* create */, size_t max_box_de
} // BmffImage::BmffImage

std::string BmffImage::toAscii(uint32_t n) {
const auto p = reinterpret_cast<const char*>(&n);
std::string result(p, p + 4);
if (!isBigEndianPlatform())
std::reverse(result.begin(), result.end());
// show 0 as _
std::replace(result.begin(), result.end(), '\0', '_');
// show non 7-bit printable ascii as .
auto f = [](unsigned char c) { return c < 32 || c > 126; };
std::replace_if(result.begin(), result.end(), f, '.');
std::string result(sizeof(uint32_t), '\0');
for (size_t i = 0; i < result.size(); ++i) {
auto c = static_cast<unsigned char>(n >> (8 * (3 - i)));
if (c == 0)
result[i] = '_';
else if (c < 32 || c > 126)
result[i] = '.';
else
result[i] = static_cast<char>(c);
}
return result;
}

Expand Down
6 changes: 6 additions & 0 deletions src/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ bool Image::isLittleEndianPlatform() {
uint64_t Image::byteSwap(uint64_t value, bool bSwap) {
#ifdef __cpp_lib_byteswap
return bSwap ? std::byteswap(value) : value;
#elif defined(_MSC_VER)
return bSwap ? _byteswap_uint64(value) : value;
#else
uint64_t result = 0;
auto source_value = reinterpret_cast<const byte*>(&value);
Expand All @@ -199,6 +201,8 @@ uint64_t Image::byteSwap(uint64_t value, bool bSwap) {
uint32_t Image::byteSwap(uint32_t value, bool bSwap) {
#ifdef __cpp_lib_byteswap
return bSwap ? std::byteswap(value) : value;
#elif defined(_MSC_VER)
return bSwap ? _byteswap_ulong(value) : value;
#else
uint32_t result = 0;
result |= (value & 0x000000FFU) << 24;
Expand All @@ -212,6 +216,8 @@ uint32_t Image::byteSwap(uint32_t value, bool bSwap) {
uint16_t Image::byteSwap(uint16_t value, bool bSwap) {
#ifdef __cpp_lib_byteswap
return bSwap ? std::byteswap(value) : value;
#elif defined(_MSC_VER)
return bSwap ? _byteswap_ushort(value) : value;
#else
uint16_t result = 0;
result |= (value & 0x00FFU) << 8;
Expand Down
10 changes: 5 additions & 5 deletions src/jp2image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ Jp2Image::Jp2Image(BasicIo::UniquePtr io, bool create) : Image(ImageType::jp2, m

// Obtains the ascii version from the box.type
std::string Jp2Image::toAscii(uint32_t n) {
const auto p = reinterpret_cast<const char*>(&n);
std::string result(p, p + 4);
if (isBigEndianPlatform())
return result;
std::reverse(result.begin(), result.end());
std::string result(sizeof(uint32_t), '\0');
for (size_t i = 0; i < result.size(); ++i) {
auto c = static_cast<unsigned char>(n >> (8 * (3 - i)));
result[i] = static_cast<char>(c);
}
return result;
}

Expand Down
15 changes: 1 addition & 14 deletions src/pgfimage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,13 @@ const unsigned char pgfBlank[] = {
// class member definitions

namespace Exiv2 {
static uint32_t byteSwap_(uint32_t value, bool bSwap) {
#ifdef __cpp_lib_byteswap
return bSwap ? std::byteswap(value) : value;
#else
uint32_t result = 0;
result |= (value & 0x000000FF) << 24;
result |= (value & 0x0000FF00) << 8;
result |= (value & 0x00FF0000) >> 8;
result |= (value & 0xFF000000) >> 24;
return bSwap ? result : value;
#endif
}

static uint32_t byteSwap_(Exiv2::DataBuf& buf, size_t offset, bool bSwap) {
uint32_t v = 0;
auto p = reinterpret_cast<byte*>(&v);
int i;
for (i = 0; i < 4; i++)
p[i] = buf.read_uint8(offset + i);
uint32_t result = byteSwap_(v, bSwap);
uint32_t result = Image::byteSwap(v, bSwap);
p = reinterpret_cast<byte*>(&result);
for (i = 0; i < 4; i++)
buf.write_uint8(offset + i, p[i]);
Expand Down
12 changes: 12 additions & 0 deletions src/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,17 @@ double getDouble(const byte* buf, ByteOrder byteOrder) {
// This algorithm assumes that the internal representation of the double
// type is the 8-byte IEEE 754 binary64 format, which is common but not
// required by the C++ standard.
#ifdef __cpp_lib_bit_cast
if (byteOrder == littleEndian)
return std::bit_cast<double>(static_cast<uint64_t>(buf[7]) << 56 | static_cast<uint64_t>(buf[6]) << 48 |
static_cast<uint64_t>(buf[5]) << 40 | static_cast<uint64_t>(buf[4]) << 32 |
static_cast<uint64_t>(buf[3]) << 24 | static_cast<uint64_t>(buf[2]) << 16 |
static_cast<uint64_t>(buf[1]) << 8 | static_cast<uint64_t>(buf[0]));
return std::bit_cast<double>(static_cast<uint64_t>(buf[0]) << 56 | static_cast<uint64_t>(buf[1]) << 48 |
static_cast<uint64_t>(buf[2]) << 40 | static_cast<uint64_t>(buf[3]) << 32 |
static_cast<uint64_t>(buf[4]) << 24 | static_cast<uint64_t>(buf[5]) << 16 |
static_cast<uint64_t>(buf[6]) << 8 | static_cast<uint64_t>(buf[7]));
#else
union {
uint64_t ull_;
double d_;
Expand All @@ -330,6 +341,7 @@ double getDouble(const byte* buf, ByteOrder byteOrder) {
static_cast<uint64_t>(buf[6]) << 8 | static_cast<uint64_t>(buf[7]);
}
return u.d_;
#endif
}

size_t us2Data(byte* buf, uint16_t s, ByteOrder byteOrder) {
Expand Down
Loading