131 lines
3.2 KiB
C
131 lines
3.2 KiB
C
![]() |
/****************************************************************************
|
||
|
* Obiblob functions *
|
||
|
****************************************************************************/
|
||
|
|
||
|
/**
|
||
|
* @file obiblob.c
|
||
|
* @author Celine Mercier
|
||
|
* @date April 11th 2016
|
||
|
* @brief Functions handling Obiblob structures.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#include "obierrno.h"
|
||
|
#include "obitypes.h" // For byte_t type
|
||
|
#include "obidebug.h"
|
||
|
|
||
|
|
||
|
#define DEBUG_LEVEL 0 // TODO has to be defined somewhere else (cython compil flag?)
|
||
|
|
||
|
|
||
|
// TODO: endianness problem?
|
||
|
|
||
|
|
||
|
Obi_blob_p obi_blob(byte_t* encoded_value, uint8_t element_size, int32_t length_encoded_value, int32_t length_decoded_value)
|
||
|
{
|
||
|
Obi_blob_p blob;
|
||
|
|
||
|
// Allocate the memory for the blob structure
|
||
|
blob = (Obi_blob_p) malloc(sizeof(Obi_blob_t) + length_encoded_value);
|
||
|
if (blob == NULL)
|
||
|
{
|
||
|
obi_set_errno(OBI_MALLOC_ERROR);
|
||
|
obidebug(1, "\nError allocating memory for a blob");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// Store the number of bits on which each element is encoded
|
||
|
blob->element_size = element_size;
|
||
|
|
||
|
// Store the length (in bytes) of the encoded value
|
||
|
blob->length_encoded_value = length_encoded_value;
|
||
|
|
||
|
// Store the initial length (in bytes) of the decoded value
|
||
|
blob->length_decoded_value = length_decoded_value;
|
||
|
|
||
|
// Store the encoded value
|
||
|
memcpy(blob->value, encoded_value, length_encoded_value);
|
||
|
|
||
|
return blob;
|
||
|
}
|
||
|
|
||
|
|
||
|
Obi_blob_p obi_str_to_blob(char* value)
|
||
|
{
|
||
|
Obi_blob_p value_b;
|
||
|
int32_t length;
|
||
|
|
||
|
// Compute the number of bytes on which the value will be encoded
|
||
|
length = strlen(value) + 1; // +1 to store \0 at the end (makes retrieving faster)
|
||
|
|
||
|
value_b = obi_blob(value, ELEMENT_SIZE_STR, length, length);
|
||
|
if (value_b == NULL)
|
||
|
{
|
||
|
obidebug(1, "\nError encoding a character string in a blob");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return value_b;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char* obi_blob_to_str(Obi_blob_p value_b)
|
||
|
{
|
||
|
return value_b->value;
|
||
|
}
|
||
|
|
||
|
|
||
|
Obi_blob_p obi_seq_to_blob(char* seq)
|
||
|
{
|
||
|
Obi_blob_p value_b;
|
||
|
int32_t length_encoded_seq; // length of the encoded sequence in bytes
|
||
|
int32_t seq_length;
|
||
|
byte_t* encoded_seq;
|
||
|
|
||
|
seq_length = strlen(seq);
|
||
|
|
||
|
// Check if just ATGC and encode accordingly
|
||
|
if (only_ATGC(seq))
|
||
|
{
|
||
|
// Compute the length (in bytes) of the encoded sequence
|
||
|
length_encoded_seq = ceil((double) seq_length / (double) 4.0);
|
||
|
// Encode
|
||
|
encoded_seq = encode_seq_on_2_bits(seq, seq_length);
|
||
|
if (encoded_seq == NULL)
|
||
|
return NULL;
|
||
|
value_b = obi_blob(encoded_seq, ELEMENT_SIZE_SEQ_2, length_encoded_seq, seq_length);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Compute the length (in bytes) of the encoded sequence
|
||
|
length_encoded_seq = ceil((double) seq_length / (double) 2.0);
|
||
|
// Encode
|
||
|
encoded_seq = encode_seq_on_4_bits(seq, seq_length);
|
||
|
if (encoded_seq == NULL)
|
||
|
return NULL;
|
||
|
value_b = obi_blob(encoded_seq, ELEMENT_SIZE_SEQ_4, length_encoded_seq, seq_length);
|
||
|
}
|
||
|
|
||
|
free(encoded_seq);
|
||
|
|
||
|
return value_b;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char* obi_blob_to_seq(Obi_blob_p value_b)
|
||
|
{
|
||
|
// Decode
|
||
|
if (value_b->element_size == 2)
|
||
|
return decode_seq_on_2_bits(value_b->value, value_b->length_decoded_value);
|
||
|
else
|
||
|
return decode_seq_on_4_bits(value_b->value, value_b->length_decoded_value);
|
||
|
}
|
||
|
|
||
|
|
||
|
// TODO same for int
|
||
|
|