Commit 54a93a2d authored by Gallacchi Mattia's avatar Gallacchi Mattia
Browse files

Add memory check

parent c94ae3ee
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
cmake_minimum_required(VERSION 3.20)

project(rsvp LANGUAGES C CXX)
project(rsvp-c-cpp LANGUAGES C CXX)

include_directories(src)

add_compile_options("-Wall")

add_subdirectory(src)
add_subdirectory(tests)
 No newline at end of file

check_mem.sh

0 → 100755
+12 −0
Original line number Diff line number Diff line
#!/bin/bash

SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
cd $SCRIPTPATH/build

make

valgrind --leak-check=full \
         --show-leak-kinds=all \
         --track-origins=yes \
         --log-file=valgrind-out.txt \
         ./tests/testpp
 No newline at end of file
+3 −3
Original line number Diff line number Diff line
@@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.20)
project(rsvp)

file(GLOB SRC *.c)

add_library(${PROJECT_NAME} ${SRC})

file(GLOB SRC *.c *.hpp)
file(GLOB SRC *.cpp)
add_library(${PROJECT_NAME}pp ${SRC})
target_link_libraries(${PROJECT_NAME}pp rsvp)
 No newline at end of file
+288 −101
Original line number Diff line number Diff line
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "rsvp.h"

RSVP_TYPE get_type(char *type)
@@ -31,10 +32,12 @@ int count_tokens(char *str, char delimiter)
    return counter;  
}

void get_vecd_elem(char *token, rsvp_vecd_elem_t* elem)
rsvp_vecd_elem_t* get_vecd_elem(char *token)
{
    char *value = NULL, *begin = token;
    rsvp_vecd_elem_t* elem = NULL;
    int index = 0;
    size_t name_len = 0;

    while ((*token != '\0') && (value == NULL)) {

@@ -44,31 +47,41 @@ void get_vecd_elem(char *token, rsvp_vecd_elem_t* elem)
                break;
            default:
                index++;
                token++;
                break;
        }
        token++;
    }

    elem->name = (char*)malloc(index);
    memcpy(elem->name, begin, index);
    elem = (rsvp_vecd_elem_t*)malloc(sizeof(rsvp_vecd_elem_t));
    if (!elem) {
        error_code = ALLOCATION_FAILED;
        goto exit;
    }

    elem->value = strtod(value, NULL);
    name_len = index + 1;
    elem->name = (char*)malloc(name_len);
    if (!elem->name) {
        error_code = ALLOCATION_FAILED;
        goto free_elem;
    }

void get_vecd(char *value, rsvp_var_t* var)
{
    char *token, delimiter = '=';
    var->len = count_tokens(value, delimiter);
    var->value = (rsvp_vecd_elem_t*)malloc(sizeof(rsvp_vecd_elem_t) * var->len);
    rsvp_vecd_elem_t* begin = (rsvp_vecd_elem_t*)var->value;
    memset(elem->name, 0, name_len);
    memcpy(elem->name, begin, name_len - 1);
    
    delimiter = ',';
    token = strtok(value, &delimiter);
    for (int i = 0; i < var->len; i++) {
        get_vecd_elem(token, begin++);
        token = strtok(NULL, &delimiter);
    if ((elem->value = strtod(value, NULL)) == 0.0) {
        error_code = DBL_CONVERSION_FAILED;
        sprintf(error_str, "Failed to convert %s to double", value);
        goto free_name;
    }

    return elem;

free_name:
    free(elem->name);
free_elem:
    free(elem);
exit:
    return NULL;
}

rsvp_vecd_elem_t* rsvp_var_get_vecd_elem(rsvp_var_t* var, int index)
@@ -76,15 +89,16 @@ rsvp_vecd_elem_t* rsvp_var_get_vecd_elem(rsvp_var_t* var, int index)
    if (index >= var->len) {
        return NULL;
    }

    return (rsvp_vecd_elem_t*)var->value + index;
    return (rsvp_vecd_elem_t*)var->value.vecd + index;
}

void process_args(char *arg, rsvp_var_t* var)
rsvp_var_t* process_args(char *arg)
{
    char *begin = arg;
    char *value = NULL;
    char *begin = arg, *name = NULL, *value = NULL;
    RSVP_TYPE type = STR;
    int index = 0, type_start = 0;
    rsvp_var_t* var = NULL;
    size_t name_len = 0;

    // Search for the variable name
    while ((*arg != '\0') && (value == NULL))  {
@@ -92,27 +106,28 @@ void process_args(char *arg, rsvp_var_t* var)
        switch (*arg)
        {
        case '(':
            var->name = (char*)malloc(index + 1);
            memcpy(var->name, begin, index);
            var->name[index] = '\0';
            name_len = index + 1;
            name = (char*)malloc(name_len);
            memset(name, 0, name_len);
            memcpy(name, begin, name_len - 1);
            type_start = index + 1;

            break;

        case ')':
        {
            size_t type_len = (index - type_start) + 1;
            char type[type_len];
            memcpy(type, &begin[type_start], type_len);
            var->type = get_type(type);
            char type_str[type_len];
            memcpy(type_str, &begin[type_start], type_len);
            type = get_type(type_str);
            break;
        }
        case '=':
            // We found the variable value
            if (var->name == NULL) {
                var->name = (char*)malloc(index + 1);
                memcpy(var->name, begin, index);
                var->name[index] = '\0';
            if (name == NULL) {
                name_len = index + 1;
                name = (char*)malloc(name_len);
                memset(name, 0, name_len);
                memcpy(name, begin, name_len - 1);
            }
            value = ++arg;
            break;
@@ -125,51 +140,73 @@ void process_args(char *arg, rsvp_var_t* var)
        arg++;
    }

    switch (var->type) {
    switch (type) {

        case INT:
        {
            int value_int;
            var->value = malloc(sizeof(int));
            value_int = strtol(value, NULL, 0);
            memcpy(var->value, &value_int, sizeof(int));
            int value_int = strtol(value, NULL, 0);
            var = rsvp_var_create_int(name, value_int);
            break;
        }

        case DBL:
        {
            double value_dbl;
            var->value = malloc(sizeof(double));
            value_dbl = strtod(value, NULL);
            memcpy(var->value, &value_dbl, sizeof(double));
            double value_dbl = strtod(value, NULL);
            var = rsvp_var_create_double(name, value_dbl);
            break;
        }

        case BOOL:
        {
            int val = 0;
            var->value = malloc(1);
            if (strcmp(value, "TRUE") == 0) {
                val = 1;
            }
            memcpy(var->value, &val, 1);
            var = rsvp_var_create_bool(name, val);
            break;
        }

        case VECD:
        {
            get_vecd(++value, var);
            char *token = NULL, delimiter = '=';
            int elem_count = count_tokens(value, delimiter);
            var = rsvp_var_create_vecd(name);

            delimiter = ',';
            token = strtok(++value, &delimiter);
            for (int i = 0; i < elem_count; i++) {
                rsvp_vecd_elem_t *elem = NULL;
                elem = get_vecd_elem(token);
                if (!elem) {
                    printf("Error: %s\n", error_str);
                    continue;
                }
                rsvp_vecd_add_elem(var, elem->name, elem->value);
                free(elem->name);
                free(elem);
                token = strtok(NULL, &delimiter);
            }

            break;
        }

        case VECS:
        {
            char *token = NULL, delimiter = '\t';
            int elem_count = count_tokens(value, delimiter) + 1;
            var = rsvp_var_create_vecs(name);

            token = strtok(value, &delimiter);
            for (int i = 0; i < elem_count; i++) {
                rsvp_vecs_add_elem(var, token);
                token = strtok(NULL, &delimiter);
            }
            break;
        }


        default:
            var->value = (char*)malloc(strlen(value) + 1);
            memset(var->value, 0, strlen(value) + 1);
            memcpy(var->value, value, strlen(value));
            var = rsvp_var_create_string(name, value);
            break;

    }
@@ -178,15 +215,29 @@ void process_args(char *arg, rsvp_var_t* var)
    rsvp_var_print(var);
#endif

    free(name);

    if (!var) {
        error_code = VAR_CREATION_FAILED;
        printf("Failed to add arg\n");
        return NULL;
    }

    return var;
}

rsvp_data_t *rsvp_data_parse(char* data)
{
    char *token;
    char **args;
    char *token = NULL;
    char **args  =NULL;
    char delimiter = ';';
    size_t index = 0;
    size_t index = 0, token_len = 0;

    rsvp_data_t *rsvp_data = (rsvp_data_t*)malloc(sizeof(rsvp_data_t));
    if (!rsvp_data) {
        error_code = ALLOCATION_FAILED;
        return NULL;
    }

    memset(rsvp_data, 0, sizeof(rsvp_data_t));
    rsvp_data->args_count = count_tokens(data, delimiter);
@@ -194,8 +245,10 @@ rsvp_data_t *rsvp_data_parse(char* data)

    // Get command string
    token = strtok(data, &delimiter);
    rsvp_data->cmd = (char*)malloc(strlen(token));
    memcpy(rsvp_data->cmd, token, strlen(token));
    token_len = strlen(token) + 1;
    rsvp_data->cmd = (char*)malloc(token_len);
    memset(rsvp_data->cmd, 0, token_len);
    memcpy(rsvp_data->cmd, token, token_len - 1);

    // Process args
    while (token != NULL) {
@@ -205,22 +258,38 @@ rsvp_data_t *rsvp_data_parse(char* data)
            break;
        }

        token_len = strlen(token) + 1;

#ifdef DEBUG
        printf("*** DBG *** token[%d]: %s\n", rsvp_data->args_count, token);
#endif
        args[index] = (char*)malloc(strlen(token));
        memcpy(args[index++], token, strlen(token));
        args[index] = (char*)malloc(token_len);
        memset(args[index], 0, token_len);
        memcpy(args[index++], token, token_len - 1);
    }

    rsvp_data->args = (rsvp_var_t*)malloc(rsvp_data->args_count * sizeof(rsvp_var_t));
    rsvp_data->args = (rsvp_var_t**)malloc(rsvp_data->args_count * sizeof(rsvp_var_t*));
    if (!rsvp_data->args) {
        error_code = ALLOCATION_FAILED;
        return NULL;
    }

#ifdef DEBUG
    rsvp_data_print(rsvp_data);
#endif

    for(int i = 0; i < rsvp_data->args_count; i++) {
        process_args(args[i], &rsvp_data->args[i]);
        rsvp_data->args[i] = process_args(args[i]);
        if (!rsvp_data->args[i]) {
            break;
        }
    }

    for (int i = 0; i < rsvp_data->args_count; i++) {
        free(args[i]);
    }

    free(args);

    return rsvp_data;
}
@@ -232,77 +301,119 @@ void rsvp_var_print(rsvp_var_t *var)
    switch (var->type)
    {
    case INT:
        printf("%d\n", *(int*)var->value);
        printf("%d\n", var->value.i);
        break;
    
    case DBL:
        printf("%f\n", *(double*)var->value);
        printf("%f\n", var->value.d);
        break;

    case BOOL:
        printf("%d\n", *(int*)var->value);
        printf("%d\n", var->value.b);
        break;
    
    case VECD:
        printf("[");
        for (int i = 0; i < var->len; i++) {
            rsvp_vecd_elem_t* elem = rsvp_var_get_vecd_elem(var, i);
            printf("%s=%f,", elem->name, elem->value);
            printf("%s=%f", elem->name, elem->value);
            if (i < var->len - 1) {
                printf(",");
            }
            elem++;
        }
        printf("]\n");
        break;
    
    case VECS:
        for (int i = 0; i < var->len; i++) {
            printf("%s\t", var->value.vecs[i]);
        }
        printf("\n");
        break;

    default:
        printf("%s\n", (char*)var->value);
        printf("%s\n", var->value.s);
        break;
    }
}

void rsvp_data_print(rsvp_data_t *data)
{
    printf("Command: %s, args:\n", data->cmd);
    printf("Command: %s, args [%d]:\n", data->cmd, data->args_count);

    for(int i = 0; i < data->args_count; i++) {
        rsvp_var_print(&data->args[i]);
        printf("ARG[%d] => ", i);
        rsvp_var_print(data->args[i]);
    }
}

void rsvp_data_free(rsvp_data_t *data)
{
    if (data != NULL) {
        for (int i = 0; i < data->args_count; i++) {
        rsvp_var_free(&data->args[i]);
            rsvp_var_free(data->args[i]);
        }

        if (data->args)
            free(data->args);
        
        free(data->cmd);
        free(data);
    }
}

void rsvp_var_free(rsvp_var_t *var) 
{
    free(var->name);

    if (var) {
        switch (var->type)
        {
        case VECD:
            for (int i = 0; i < var->len; i++) {
                rsvp_vecd_elem_t* elem = rsvp_var_get_vecd_elem(var, i);
                free(elem->name);
            elem++;
            }
            free(var->value.vecd);
            break;

        case VECS:
            for (int i = 0; i < var->len; i++) {
                free(var->value.vecs[i]);
            }
            free(var->value.vecs);
            break;

        case STR:
            free(var->value.s);
            break;
        
        default:
        free(var->value);
            break;
        }

        free(var->name);
        free(var);
    }
}

rsvp_var_t* rsvp_var_init(char *name)
{
    size_t len = strlen(name) + 1;
    rsvp_var_t *var = (rsvp_var_t*)malloc(sizeof(rsvp_var_t));
    if (!var) {
        error_code = ALLOCATION_FAILED;
        return NULL;
    }
    memset(var, 0, sizeof(rsvp_var_t));
    var->name = (char*)malloc(strlen(name));
    memcpy(var->name, name, strlen(name));
    
    var->name = (char*)malloc(len);
    if (!var->name) {
        error_code = ALLOCATION_FAILED;
        free(var);
        return NULL;
    }
    memset(var->name, '\0', len);
    memcpy(var->name, name, len - 1);

    return var;
}
@@ -310,9 +421,11 @@ rsvp_var_t* rsvp_var_init(char *name)
rsvp_var_t* rsvp_var_create_int(char *name, int value)
{
    rsvp_var_t *var = rsvp_var_init(name);
    if (!var)
        return NULL;

    var->type = INT;
    var->value = malloc(sizeof(int));
    memcpy(var->value, &value, sizeof(int));
    var->value.i = value;

    return var;
}
@@ -320,17 +433,23 @@ rsvp_var_t* rsvp_var_create_int(char *name, int value)
rsvp_var_t* rsvp_var_create_double(char *name, double value)
{
    rsvp_var_t *var = rsvp_var_init(name);
    if (!var)
        return NULL;

    var->type = DBL;
    var->value = malloc(sizeof(double));
    memcpy(var->value, &value, sizeof(double));
    var->value.d = value;

    return var;
}

rsvp_var_t* rsvp_var_create_bool(char *name, int value)
{
    rsvp_var_t *var = rsvp_var_create_int(name, value);
    rsvp_var_t *var = rsvp_var_init(name);
    if (!var)
        return NULL;

    var->type = BOOL;
    var->value.b = value;

    return var;
}
@@ -338,28 +457,96 @@ rsvp_var_t* rsvp_var_create_bool(char *name, int value)
rsvp_var_t* rsvp_var_create_string(char *name, char* value)
{
    rsvp_var_t *var = rsvp_var_init(name);
    if (!var)
        return NULL;

    var->type = STR;
    var->value = malloc(strlen(value));
    memcpy(var->value, &value, strlen(value));
    var->value.s = (char*)malloc(strlen(value));
    if (!var->value.s) {
        error_code = ALLOCATION_FAILED;
        return NULL;
    }
    memcpy(var->value.s, value, strlen(value));

    return var;
}

rsvp_var_t* rsvp_var_create_vecd(char *name, rsvp_vecd_elem_t *elem, unsigned int count)
rsvp_var_t* rsvp_var_create_vecd(char *name)
{
    rsvp_var_t *var = rsvp_var_init(name);
    if (!var)
        return NULL;
        
    var->type = VECD;
    var->value = malloc(count * sizeof(rsvp_vecd_elem_t));
    var->len = count;

    for (int i = 0; i < count; i++) {
        // rsvp_vecd_elem_t *elem = rsvp_var_get_vecd_elem(var, i);
        // elem->name = (char*)malloc(strlen(names));
        // memcpy(elem->name, names, strlen(names));
        // names += strlen(names);
        // elem->value = values[i];
    return var;
}

int rsvp_vecd_add_elem(rsvp_var_t* vecd, char* name, double value)
{
    size_t name_len = strlen(name) + 1;
    
    if (vecd->type != VECD) {
        error_code = WRONG_VARIABLE_TYPE;
        return -1;
    }

    vecd->len += 1;

    vecd->value.vecd = (rsvp_vecd_elem_t*)realloc(vecd->value.vecd, vecd->len * sizeof(rsvp_vecd_elem_t));
    if (!vecd->value.vecd) {
        error_code = ALLOCATION_FAILED;
        vecd->len -= 1;
        return -1;
    }

    vecd->value.vecd[vecd->len - 1].name = (char*)malloc(name_len);
    if (!vecd->value.vecd[vecd->len - 1].name) {

    }
    memset(vecd->value.vecd[vecd->len - 1].name, 0, name_len);
    memcpy(vecd->value.vecd[vecd->len - 1].name, name, name_len - 1);
    vecd->value.vecd[vecd->len - 1].value = value;

    return 0;
}

rsvp_var_t* rsvp_var_create_vecs(char *name)
{
    rsvp_var_t *var = rsvp_var_init(name);
    if (!var)
        return NULL;
        
    var->type = VECS;

    return var;
}

int rsvp_vecs_add_elem(rsvp_var_t* vecs, char *value)
{
    size_t value_len = strlen(value) + 1;

    if (vecs->type != VECS) {
        error_code = WRONG_VARIABLE_TYPE;
        return -1;
    }

    vecs->len += 1;

    vecs->value.vecs = (char**)realloc(vecs->value.vecs, vecs->len * sizeof(char*));
    if (!vecs->value.vecs) {
        error_code = ALLOCATION_FAILED;
        return -1;
    }

    vecs->value.vecs[vecs->len - 1] = (char*)malloc(value_len);
    if (!vecs->value.vecs[vecs->len - 1]) {
        error_code = ALLOCATION_FAILED;
        return -1;
    }

    memset(vecs->value.vecs[vecs->len - 1], 0, value_len);
    memcpy(vecs->value.vecs[vecs->len - 1], value, value_len - 1);

    return NO_ERROR;
}
 No newline at end of file
+32 −3
Original line number Diff line number Diff line
@@ -3,6 +3,18 @@

#define TYPE_COUNT  6

#define ERR_STR_SIZE            256
#define NO_ERROR                0
#define ALLOCATION_FAILED       (NO_ERROR + 1)
#define VAR_CREATION_FAILED     (ALLOCATION_FAILED + 1)
#define DBL_CONVERSION_FAILED   (VAR_CREATION_FAILED + 1)
#define INT_CONVERSION_FAILED   4
#define BOOL_CONVERSION_FAILED  5
#define WRONG_VARIABLE_TYPE     6

static int error_code = NO_ERROR;
static char error_str[ERR_STR_SIZE] = {0};

typedef enum  {
    STR = 0,
    INT,
@@ -32,17 +44,31 @@ struct rsvp_vecs_elem {
};
typedef struct rsvp_vecs_elem rsvp_vecs_elem_t;

typedef union
{
    int i;
    double d;
    int b;
    char *s;
    rsvp_vecd_elem_t* vecd;
    char** vecs;

} value_t;

struct rsvp_var {
    char *name;
    int len;
    RSVP_TYPE type;
    void *value;
    value_t value;
    // void *value;
    
    
};
typedef struct rsvp_var rsvp_var_t;

struct rsvp_data {
    char *cmd;
    rsvp_var_t *args;
    rsvp_var_t **args;
    unsigned int args_count;
};
typedef struct rsvp_data rsvp_data_t;
@@ -58,7 +84,10 @@ extern rsvp_var_t* rsvp_var_create_int(char *name, int value);
extern rsvp_var_t* rsvp_var_create_double(char *name, double value);
extern rsvp_var_t* rsvp_var_create_bool(char *name, int value);
extern rsvp_var_t* rsvp_var_create_string(char *name, char* value);
extern rsvp_var_t* rsvp_var_create_vecd(char *name, rsvp_vecd_elem_t *elem, unsigned int count);
extern rsvp_var_t* rsvp_var_create_vecd(char *name);
extern int rsvp_vecd_add_elem(rsvp_var_t* vecd, char* name, double value);
extern rsvp_var_t* rsvp_var_create_vecs(char *name);
extern int rsvp_vecs_add_elem(rsvp_var_t* vecs, char* value);

extern rsvp_vecd_elem_t* rsvp_var_get_vecd_elem(rsvp_var_t* var, int index);
extern void rsvp_var_print(rsvp_var_t *var);
Loading