| @@ -57,6 +57,7 @@ carla-discovery-posix32 | |||
| carla-discovery-posix64 | |||
| source/tests/ANSI | |||
| source/tests/Base64 | |||
| source/tests/CarlaString | |||
| source/tests/Print | |||
| source/tests/RtList | |||
| @@ -15,7 +15,9 @@ | |||
| * For a full copy of the GNU General Public License see the GPL.txt file | |||
| */ | |||
| #if 1 | |||
| #include "standalone/carla_standalone.cpp" | |||
| #if 0 | |||
| #include "CarlaDefines.hpp" | |||
| #include "CarlaMIDI.h" | |||
| #include "ladspa_rdf.hpp" | |||
| @@ -30,6 +32,7 @@ | |||
| #include "CarlaUtils.hpp" | |||
| #include "CarlaBackendUtils.hpp" | |||
| #include "CarlaBase64Utils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| #include "CarlaLibUtils.hpp" | |||
| #include "CarlaOscUtils.hpp" | |||
| @@ -0,0 +1,106 @@ | |||
| /* | |||
| * Carla Tests | |||
| * 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 | |||
| */ | |||
| #include "CarlaBase64Utils.hpp" | |||
| #include "CarlaString.hpp" | |||
| int main() | |||
| { | |||
| CARLA_ASSERT(std::strlen(kBase64) == 64); | |||
| struct Blob { | |||
| char s[4]; | |||
| int i; | |||
| double d; | |||
| char padding[100]; | |||
| void* ptr; | |||
| Blob() | |||
| : s{'1', 's', 't', 0}, | |||
| i(228), | |||
| d(3.33333333333), | |||
| ptr((void*)0x500) {} | |||
| } blob; | |||
| // binary -> base64 | |||
| void* const test0 = &blob; | |||
| size_t test0Len = sizeof(Blob); | |||
| char buf0[carla_base64_encoded_len(test0Len) + 1]; | |||
| carla_base64_encode((const uint8_t*)test0, test0Len, buf0); | |||
| printf("BINARY '%s'\n", buf0); | |||
| char buf0dec[carla_base64_decoded_max_len(buf0)]; | |||
| carla_base64_decode(buf0, (uint8_t*)buf0dec); | |||
| Blob blobTester; | |||
| blobTester.s[0] = 0; | |||
| blobTester.i = 0; | |||
| blobTester.d = 9999.99999999999999; | |||
| std::memcpy(&blobTester, buf0dec, sizeof(Blob)); | |||
| CARLA_ASSERT(std::strcmp(blobTester.s, "1st") == 0); | |||
| CARLA_ASSERT(blobTester.i == 228); | |||
| CARLA_ASSERT(blobTester.d == 3.33333333333); | |||
| // string -> base64 | |||
| const char* const test1 = "Hello World!"; | |||
| size_t test1Len = std::strlen(test1); | |||
| char buf1[carla_base64_encoded_len(test1Len) + 1]; | |||
| carla_base64_encode((const uint8_t*)test1, test1Len, buf1); | |||
| printf("'%s' => '%s'\n", test1, buf1); | |||
| // base64 -> string | |||
| const char* const test2 = "SGVsbG8gV29ybGQh"; | |||
| char buf2[carla_base64_decoded_max_len(test2)]; | |||
| carla_base64_decode(test2, (uint8_t*)buf2); | |||
| printf("'%s' => '%s'\n", test2, buf2); | |||
| printf("'%s' == '%s'\n", buf1, test2); | |||
| printf("'%s' == '%s'\n", buf2, test1); | |||
| CARLA_ASSERT(std::strcmp(buf1, test2) == 0); | |||
| CARLA_ASSERT(std::strcmp(buf2, test1) == 0); | |||
| // ----------------------------------------------------------------- | |||
| blob.s[0] = 'X'; | |||
| blob.i = 92320; | |||
| blob.d = 9999887.99999999999999; | |||
| CarlaString string; | |||
| string.importBinaryAsBase64<Blob>(&blob); | |||
| Blob* blob3 = string.exportAsBase64Binary<Blob>(); | |||
| CARLA_ASSERT(std::strcmp(blob3->s, blob.s) == 0); | |||
| CARLA_ASSERT(blob3->i == blob.i); | |||
| CARLA_ASSERT(blob3->d == blob.d); | |||
| CARLA_ASSERT(blob3->ptr == blob.ptr); | |||
| delete blob3; | |||
| // ----------------------------------------------------------------- | |||
| return 0; | |||
| } | |||
| @@ -14,16 +14,19 @@ BUILD_CXX_FLAGS += -I../backend -I../includes -I../utils -Wall -Wextra | |||
| ANSI_CXX_FLAGS = -ansi -pedantic -pedantic-errors -Wunused-parameter -Wuninitialized -Wno-vla | |||
| ANSI_CXX_FLAGS += -Wcast-qual -Wconversion -Wsign-conversion -Wlogical-op -Waggregate-return | |||
| ANSI_CXX_FLAGS += -std=c++11 -Wzero-as-null-pointer-constant | |||
| ANSI_CXX_FLAGS += -DVESTIGE_HEADER | |||
| ANSI_CXX_FLAGS += -DVESTIGE_HEADER -shared -fPIC | |||
| TARGETS = ANSI CarlaString RtList Thread Print | |||
| TARGETS = ANSI_ Base64 CarlaString RtList Thread Print | |||
| all: $(TARGETS) RUN | |||
| # -------------------------------------------------------------- | |||
| ANSI: ANSI.cpp | |||
| $(CXX) $^ $(BUILD_CXX_FLAGS) $(ANSI_CXX_FLAGS) $(LINK_FLAGS) -o $@ | |||
| ANSI_: ANSI.cpp | |||
| $(CXX) $^ $(BUILD_CXX_FLAGS) $(ANSI_CXX_FLAGS) $(LINK_FLAGS) -o ANSI # $@ | |||
| Base64: Base64.cpp | |||
| $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@ | |||
| CarlaString: CarlaString.cpp | |||
| $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@ | |||
| @@ -44,6 +47,7 @@ GL_: GL.cpp | |||
| RUN: $(TARGETS) | |||
| # ./CarlaString && ./RtList && ./Thread | |||
| # ./Base64 | |||
| # ./GL | |||
| # -------------------------------------------------------------- | |||
| @@ -0,0 +1,185 @@ | |||
| /* | |||
| * 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 = (const uint8_t*)raw; | |||
| uint8_t* encodedBytes = (uint8_t*)encoded; | |||
| size_t rawBitLen = 8*len; | |||
| unsigned int bit; | |||
| unsigned int tmp; | |||
| for (bit = 0; bit < rawBitLen; bit += 6) | |||
| { | |||
| tmp = (rawBytes[bit/8] << (bit % 8)) | (rawBytes[bit/8 + 1] >> (8 - (bit % 8))); | |||
| tmp = (tmp >> 2) & 0x3f; | |||
| *(encodedBytes++) = 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) | |||
| { | |||
| char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |||
| const uint8_t* encodedBytes = (const uint8_t*)encoded; | |||
| uint8_t* rawBytes = (uint8_t*)raw; | |||
| uint8_t encodedByte; | |||
| unsigned int bit = 0; | |||
| unsigned int padCount = 0; | |||
| /* Zero the raw data */ | |||
| std::memset(raw, 0, 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) | |||
| { | |||
| carla_debug("Base64-encoded string \"%s\" has invalid pad sequence", encoded); | |||
| return 0; | |||
| } | |||
| /* Process normal characters */ | |||
| char* match = std::strchr(base64, encodedByte); | |||
| if (match == nullptr) | |||
| { | |||
| carla_debug("Base64-encoded string \"%s\" contains invalid character '%c'", encoded, encodedByte); | |||
| return 0; | |||
| } | |||
| int decoded = match - base64; | |||
| /* 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 \"%s\" to: \"%s\"\n", encoded, raw); | |||
| CARLA_ASSERT(len <= carla_base64_decoded_max_len(encoded)); | |||
| /* Return length in bytes */ | |||
| return len; | |||
| } | |||
| #endif // __CARLA_BASE64_UTILS_HPP__ | |||
| @@ -18,6 +18,7 @@ | |||
| #ifndef __CARLA_STRING_HPP__ | |||
| #define __CARLA_STRING_HPP__ | |||
| #include "CarlaBase64Utils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| // ------------------------------------------------- | |||
| @@ -250,6 +251,71 @@ public: | |||
| } | |||
| } | |||
| void toBase64() | |||
| { | |||
| importBinaryAsBase64((const uint8_t*)buffer, bufferLen); | |||
| } | |||
| void fromBase64() | |||
| { | |||
| uint8_t buffer2[carla_base64_decoded_max_len(buffer)]; | |||
| if (unsigned int len = carla_base64_decode(buffer, buffer2)) | |||
| _dup((char*)buffer2, len); | |||
| else | |||
| clear(); | |||
| } | |||
| void importBinaryAsBase64(const uint8_t* const raw, const size_t rawLen) | |||
| { | |||
| const size_t rawBufferSize = carla_base64_encoded_len(rawLen) + 1; | |||
| char rawBuffer[rawBufferSize]; | |||
| carla_base64_encode(raw, rawLen, rawBuffer); | |||
| _dup(rawBuffer, rawBufferSize-1); | |||
| } | |||
| template<typename T> | |||
| void importBinaryAsBase64(const T* const t) | |||
| { | |||
| const size_t tSize = sizeof(T); | |||
| importBinaryAsBase64((const uint8_t*)t, tSize); | |||
| } | |||
| size_t exportAsBase64Binary(uint8_t** const rawPtr) | |||
| { | |||
| uint8_t binaryBuffer[carla_base64_decoded_max_len(buffer)]; | |||
| if (unsigned int len = carla_base64_decode(buffer, binaryBuffer)) | |||
| { | |||
| uint8_t* const binaryBufferHeap = new uint8_t[len]; | |||
| std::memcpy(binaryBufferHeap, binaryBuffer, len); | |||
| *rawPtr = binaryBufferHeap; | |||
| return len; | |||
| } | |||
| return 0; | |||
| } | |||
| template<typename T> | |||
| T* exportAsBase64Binary() | |||
| { | |||
| uint8_t binaryBuffer[carla_base64_decoded_max_len(buffer)]; | |||
| if (unsigned int len = carla_base64_decode(buffer, binaryBuffer)) | |||
| { | |||
| CARLA_ASSERT_INT2(len == sizeof(T), len, sizeof(T)); | |||
| T* const t = new T(); | |||
| std::memcpy(t, binaryBuffer, len); | |||
| return t; | |||
| } | |||
| return nullptr; | |||
| } | |||
| // --------------------------------------------- | |||
| // public operators | |||