mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-09-02 15:45:12 +00:00
Alpha 1.0.10: unpinning converted chat on demand.
If we want to pin a chat and we have reached the limit we now check for a deactivated (converted to supergroup) chat that is pinned and is not in the chats list and just silently unpin it if it is found. Also possible UB fix for a waveform encoding and decoding.
This commit is contained in:
@@ -1659,20 +1659,54 @@ void DocumentData::notifyLayoutChanged() const {
|
||||
}
|
||||
|
||||
VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit) {
|
||||
VoiceWaveform result((encoded5bit.size() * 8) / 5, 0);
|
||||
for (int32 i = 0, l = result.size(); i < l; ++i) { // read each 5 bit of encoded5bit as 0-31 unsigned char
|
||||
int32 byte = (i * 5) / 8, shift = (i * 5) % 8;
|
||||
result[i] = (((*(uint16*)(encoded5bit.constData() + byte)) >> shift) & 0x1F);
|
||||
auto bitsCount = static_cast<int>(encoded5bit.size() * 8);
|
||||
auto valuesCount = bitsCount / 5;
|
||||
if (!valuesCount) {
|
||||
return VoiceWaveform();
|
||||
}
|
||||
|
||||
// Read each 5 bit of encoded5bit as 0-31 unsigned char.
|
||||
// We count the index of the byte in which the desired 5-bit sequence starts.
|
||||
// And then we read a uint16 starting from that byte to guarantee to get all of those 5 bits.
|
||||
//
|
||||
// BUT! if it is the last byte we have, we're not allowed to read a uint16 starting with it.
|
||||
// Because it will be an overflow (we'll access one byte after the available memory).
|
||||
// We see, that only the last 5 bits could start in the last available byte and be problematic.
|
||||
// So we read in a general way all the entries in a general way except the last one.
|
||||
auto result = VoiceWaveform(valuesCount, 0);
|
||||
auto bitsData = encoded5bit.constData();
|
||||
for (auto i = 0, l = valuesCount - 1; i != l; ++i) {
|
||||
auto byteIndex = (i * 5) / 8;
|
||||
auto bitShift = (i * 5) % 8;
|
||||
auto value = *reinterpret_cast<const uint16*>(bitsData + byteIndex);
|
||||
result[i] = static_cast<char>((value >> bitShift) & 0x1F);
|
||||
}
|
||||
auto lastByteIndex = ((valuesCount - 1) * 5) / 8;
|
||||
auto lastBitShift = ((valuesCount - 1) * 5) % 8;
|
||||
auto lastValue = (lastByteIndex == encoded5bit.size() - 1)
|
||||
? static_cast<uint16>(*reinterpret_cast<const uchar*>(bitsData + lastByteIndex))
|
||||
: *reinterpret_cast<const uint16*>(bitsData + lastByteIndex);
|
||||
result[valuesCount - 1] = static_cast<char>((lastValue >> lastBitShift) & 0x1F);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray documentWaveformEncode5bit(const VoiceWaveform &waveform) {
|
||||
QByteArray result((waveform.size() * 5 + 7) / 8, 0);
|
||||
for (int32 i = 0, l = waveform.size(); i < l; ++i) { // write each 0-31 unsigned char as 5 bit to result
|
||||
int32 byte = (i * 5) / 8, shift = (i * 5) % 8;
|
||||
(*(uint16*)(result.data() + byte)) |= (uint16(waveform.at(i) & 0x1F) << shift);
|
||||
auto bitsCount = waveform.size() * 5;
|
||||
auto bytesCount = (bitsCount + 7) / 8;
|
||||
auto result = QByteArray(bytesCount + 1, 0);
|
||||
auto bitsData = result.data();
|
||||
|
||||
// Write each 0-31 unsigned char as 5 bit to result.
|
||||
// We reserve one extra byte to be able to dereference any of required bytes
|
||||
// as a uint16 without overflowing, even the byte with index "bytesCount - 1".
|
||||
for (auto i = 0, l = waveform.size(); i < l; ++i) {
|
||||
auto byteIndex = (i * 5) / 8;
|
||||
auto bitShift = (i * 5) % 8;
|
||||
auto value = (static_cast<uint16>(waveform[i]) & 0x1F) << bitShift;
|
||||
*reinterpret_cast<uint16*>(bitsData + byteIndex) |= value;
|
||||
}
|
||||
result.resize(bytesCount);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user