Browse Source

Add base64 related functions; misc changes

tags/1.9.4
falkTX 12 years ago
parent
commit
2f66a53c27
7 changed files with 517 additions and 162 deletions
  1. +1
    -0
      .gitignore
  2. +147
    -157
      source/backend/standalone/carla_standalone.cpp
  3. +4
    -1
      source/tests/ANSI.cpp
  4. +106
    -0
      source/tests/Base64.cpp
  5. +8
    -4
      source/tests/Makefile
  6. +185
    -0
      source/utils/CarlaBase64Utils.hpp
  7. +66
    -0
      source/utils/CarlaString.hpp

+ 1
- 0
.gitignore View File

@@ -57,6 +57,7 @@ carla-discovery-posix32
carla-discovery-posix64 carla-discovery-posix64


source/tests/ANSI source/tests/ANSI
source/tests/Base64
source/tests/CarlaString source/tests/CarlaString
source/tests/Print source/tests/Print
source/tests/RtList source/tests/RtList


+ 147
- 157
source/backend/standalone/carla_standalone.cpp
File diff suppressed because it is too large
View File


+ 4
- 1
source/tests/ANSI.cpp View File

@@ -15,7 +15,9 @@
* For a full copy of the GNU General Public License see the GPL.txt file * 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 "CarlaDefines.hpp"
#include "CarlaMIDI.h" #include "CarlaMIDI.h"
#include "ladspa_rdf.hpp" #include "ladspa_rdf.hpp"
@@ -30,6 +32,7 @@


#include "CarlaUtils.hpp" #include "CarlaUtils.hpp"
#include "CarlaBackendUtils.hpp" #include "CarlaBackendUtils.hpp"
#include "CarlaBase64Utils.hpp"
#include "CarlaJuceUtils.hpp" #include "CarlaJuceUtils.hpp"
#include "CarlaLibUtils.hpp" #include "CarlaLibUtils.hpp"
#include "CarlaOscUtils.hpp" #include "CarlaOscUtils.hpp"


+ 106
- 0
source/tests/Base64.cpp View File

@@ -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;
}

+ 8
- 4
source/tests/Makefile View File

@@ -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 = -ansi -pedantic -pedantic-errors -Wunused-parameter -Wuninitialized -Wno-vla
ANSI_CXX_FLAGS += -Wcast-qual -Wconversion -Wsign-conversion -Wlogical-op -Waggregate-return 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 += -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 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 CarlaString: CarlaString.cpp
$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@ $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@
@@ -44,6 +47,7 @@ GL_: GL.cpp
RUN: $(TARGETS) RUN: $(TARGETS)
# ./CarlaString && ./RtList && ./Thread # ./CarlaString && ./RtList && ./Thread
# ./Print # ./Print
# ./Base64
# ./GL # ./GL


# -------------------------------------------------------------- # --------------------------------------------------------------


+ 185
- 0
source/utils/CarlaBase64Utils.hpp View File

@@ -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__

+ 66
- 0
source/utils/CarlaString.hpp View File

@@ -18,6 +18,7 @@
#ifndef __CARLA_STRING_HPP__ #ifndef __CARLA_STRING_HPP__
#define __CARLA_STRING_HPP__ #define __CARLA_STRING_HPP__


#include "CarlaBase64Utils.hpp"
#include "CarlaJuceUtils.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 // public operators




Loading…
Cancel
Save