|
- /*
- * Carla base64 utils imported from qemu source code
- * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>
- * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * For a full copy of the GNU General Public License see the GPL.txt file
- */
-
- #ifndef __CARLA_BASE64_UTILS_HPP__
- #define __CARLA_BASE64_UTILS_HPP__
-
- #include "CarlaUtils.hpp"
-
- #include <cctype>
- #include <cstdint>
-
- static const char kBase64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- /**
- * Calculate length of base64-encoded data
- *
- * @v rawLen Raw data length
- * @ret encodedLen Encoded string length (excluding NUL)
- */
- static inline
- size_t carla_base64_encoded_len(const size_t rawLen)
- {
- return (((rawLen + 3 - 1) / 3) * 4);
- }
-
- /**
- * Calculate maximum length of base64-decoded string
- *
- * @v encoded Encoded string
- * @v maxRawLen Maximum length of raw data
- *
- * Note that the exact length of the raw data cannot be known until
- * the string is decoded.
- */
- static inline
- size_t carla_base64_decoded_max_len(const char* const encoded)
- {
- return (((std::strlen(encoded) + 4 - 1) / 4) * 3);
- }
-
- /**
- * Base64-encode data
- *
- * @v raw Raw data
- * @v len Length of raw data
- * @v encoded Buffer for encoded string
- *
- * The buffer must be the correct length for the encoded string.
- * Use something like
- *
- * char buf[carla_base64_encoded_len(len) + 1];
- *
- * (the +1 is for the terminating NUL) to provide a buffer of the correct size.
- */
- static inline
- void carla_base64_encode(const uint8_t* const raw, const size_t len, char* const encoded)
- {
- const uint8_t* rawBytes = raw;
- uint8_t* encodedBytes = (uint8_t*)encoded;
- size_t rawBitLen = 8*len;
- size_t bit, tmp;
-
- for (bit = 0; bit < rawBitLen; bit += 6)
- {
- tmp = static_cast<size_t>((rawBytes[bit/8] << (bit % 8)) | (rawBytes[bit/8 + 1] >> (8 - (bit % 8))));
- tmp = static_cast<size_t>((tmp >> 2) & 0x3f);
- CARLA_ASSERT(tmp < 64);
-
- *(encodedBytes++) = static_cast<uint8_t>(kBase64[tmp]);
- }
-
- for (; (bit % 8) != 0; bit += 6)
- *(encodedBytes++) = '=';
-
- *(encodedBytes++) = '\0';
-
- carla_debug("Base64-encoded to \"%s\"\n", encoded);
- CARLA_ASSERT(std::strlen(encoded) == carla_base64_encoded_len(len));
- }
-
- /**
- * Base64-decode string
- *
- * @v encoded Encoded string
- * @v raw Raw data
- * @ret len Length of raw data, or 0
- *
- * The buffer must be large enough to contain the decoded data.
- * Use something like
- *
- * char buf[carla_base64_decoded_max_len(encoded)];
- *
- * to provide a buffer of the correct size.
- */
- static inline
- unsigned int carla_base64_decode(const char* const encoded, uint8_t* const raw)
- {
- const uint8_t* encodedBytes = (const uint8_t*)encoded;
- uint8_t* rawBytes = raw;
- uint8_t encodedByte;
- unsigned int bit = 0;
- unsigned int padCount = 0;
-
- /* Zero the raw data */
- carla_zeroMem(raw, carla_base64_decoded_max_len(encoded));
-
- /* Decode string */
- while ((encodedByte = *(encodedBytes++)) > 0)
- {
- /* Ignore whitespace characters */
- if (std::isspace(encodedByte))
- continue;
-
- /* Process pad characters */
- if (encodedByte == '=')
- {
- if (padCount >= 2)
- {
- carla_debug("Base64-encoded string \"%s\" has too many pad characters", encoded);
- return 0;
- }
-
- padCount++;
- bit -= 2; /* unused_bits = ( 2 * padCount ) */
- continue;
- }
-
- if (padCount > 0)
- {
- carla_debug("Base64-encoded string \"%s\" has invalid pad sequence", encoded);
- return 0;
- }
-
- /* Process normal characters */
- const char* const match = std::strchr(kBase64, encodedByte);
-
- if (match == nullptr)
- {
- carla_debug("Base64-encoded string \"%s\" contains invalid character '%c'", encoded, encodedByte);
- return 0;
- }
-
- uint8_t decoded = static_cast<uint8_t>(match - kBase64);
-
- /* Add to raw data */
- decoded <<= 2;
- rawBytes[bit / 8] |= (decoded >> (bit % 8));
- rawBytes[bit / 8 + 1] |= (decoded << (8 - (bit % 8)));
- bit += 6;
- }
-
- /* Check that we decoded a whole number of bytes */
- if ((bit % 8) != 0)
- {
- carla_debug("Base64-encoded string \"%s\" has invalid bit length %d", encoded, bit);
- return 0;
- }
-
- unsigned int len = bit/8;
-
- carla_debug("Base64-decoded from \"%s\"", encoded);
- CARLA_ASSERT(len <= carla_base64_decoded_max_len(encoded));
-
- /* Return length in bytes */
- return len;
- }
-
- #endif // __CARLA_BASE64_UTILS_HPP__
|