in GLTFSDK/Inc/GLTFSDK/ResourceReaderUtils.h [111:169]
inline void Base64Decode(Base64StringView encodedData, Base64BufferView decodedData, size_t bytesToSkip)
{
if (encodedData.GetByteCount() != (decodedData.bufferByteLength + bytesToSkip))
{
throw GLTFException("The specified decode buffer's size is incorrect");
}
static const std::vector<uint8_t> decodeTable = GetDecodeTable();
uint32_t block = 0U;
uint32_t blockBits = 0U;
uint8_t* decodedBytePtr = static_cast<uint8_t*>(decodedData.buffer);
for (const auto encodedChar : encodedData)
{
// For platforms where char is unsigned (encodedChar < 0) results in a tautology warning.
// Only do that test on platforms where char is signed.
if ((std::numeric_limits<char>::is_signed && (static_cast<signed char>(encodedChar) < 0)) || (static_cast<size_t>(encodedChar) >= decodeTable.size()))
{
throw GLTFException("Invalid base64 character");
}
const auto decodedChar = decodeTable[encodedChar];
if (decodedChar == std::numeric_limits<uint8_t>::max())
{
throw GLTFException("Invalid base64 character");
}
// Each character of a base64 string encodes 6 bits of data so left shift any remaining
// bits to accomodate another character's worth of data before performing a bitwise OR
block <<= 6U;
block |= decodedChar & 0x3F;
// Keep track of how many bits of the 'block' variable are currently used
blockBits += 6U;
// If there are 8 or more bits stored in 'block' then write a single byte to the output buffer
if (blockBits >= 8U)
{
blockBits -= 8U;
if (bytesToSkip > 0)
{
bytesToSkip--;
}
else
{
// Right shift the decoded data stored in 'block' so that the byte of
// data to be written to the output buffer occupies the low-order byte
*(decodedBytePtr++) = (block >> blockBits) & 0xFF;
}
// Generate a bitmask that discards only the byte just written to the output buffer during the bitwise AND
block &= (1 << blockBits) - 1;
}
}
}