summaryrefslogblamecommitdiffstats
path: root/hw4/l4basic/l4strv.c
blob: b05ad5b787e24343ea34c44c63e9ec6978fce8fb (plain) (tree)








































































































































































































































































































                                                                               
/* vim: set sw=4 ts=4 sts=4 et: */

#include "l4strv.h"

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

LbsStrv* lbs_strv_new_with_max (size_t max) {
    LbsStrv* strv = xmalloc (sizeof (LbsStrv));
    if (strv == NULL) {
        return NULL;
    }

    if (lbs_array_init_with_max (&strv->array, sizeof (LbsArray), max) < 0) {
        free (strv);
        return NULL;
    }

    strv->ref_count = 1;
    strv->is_alloc = true;
    return strv;
}

int lbs_strv_init_with_max (LbsStrv* strv, size_t max) {
    if (lbs_array_init_with_max (&strv->array, sizeof (LbsArray), max) < 0) {
        return -1;
    }

    strv->ref_count = 1;
    strv->is_alloc = false;
    return 0;
}

void* lbs_strv_ref_generic (void* strv_generic) {
    LbsStrv* strv = LBS_STRV (strv_generic);
    strv->ref_count++;
    return strv;
}

void lbs_strv_unref_generic (void* strv_generic) {
    if (strv_generic == NULL) {
        return;
    }
    LbsStrv* strv = LBS_STRV (strv_generic);
    strv->ref_count--;
    if (strv->ref_count <= 0) {
        lbs_strv_free (strv);
    }
}

void lbs_strv_free_generic (void* strv_generic) {
    if (strv_generic == NULL) {
        return;
    }
    LbsStrv* strv = LBS_STRV (strv_generic);
    size_t i = 0;
    for (; i < lbs_strv_get_len (strv); i++) {
        LbsArray* str_wrapper = lbs_strv_get_str_wrapper (strv, i);
        lbs_array_unref (str_wrapper);
    }
    lbs_array_unref (&strv->array);
    if (strv->is_alloc) {
        free (strv);
    }
}

char* lbs_strv_dup_str (LbsStrv* strv, size_t stri) {
    LbsArray* str_wrapper = lbs_strv_get_str_wrapper (strv, stri);
    size_t len = lbs_array_get_len (str_wrapper);
    char* str = lbs_array_get_data (str_wrapper);

    char* str_new = xmalloc (len + sizeof (char));
    strncpy (str_new, str, len);
    str_new[len] = '\0';

    return str_new;
}

int lbs_strv_append_char (LbsStrv* strv, size_t stri, char chr) {
    if (chr == '\0') {
        return -1;
    }

    if (stri >= lbs_strv_get_len (strv)) {
        stri = lbs_strv_get_len (strv);
        LbsArray str_struct;
        LbsArray* str = &str_struct;
        if (lbs_array_init (str, sizeof (char)) < 0) {
            return -1;
        }
        if (lbs_array_append_data (&strv->array, str) < 0) {
            lbs_array_unref (str);
            return -1;
        }
    }
    LbsArray* str = lbs_strv_get_str_wrapper (strv, stri);
    return lbs_array_append_data (str, &chr);
}

int lbs_strv_append_str_empty (LbsStrv* strv) {
    LbsArray str_struct, *str = &str_struct;
    if (lbs_array_init (str, sizeof (char)) < 0) {
        return -1;
    }
    if (lbs_array_append_data (&strv->array, &str_struct) < 0) {
        lbs_array_unref (str);
        return -1;
    }
    return 0;
}

int lbs_strv_append_str (LbsStrv* strv, const char* bstr) {
    if (bstr == NULL) {
        return -1;
    }

    size_t len = strlen (bstr);
    char* str_copy = xmalloc (sizeof (char) * len);
    if (str_copy == NULL) {
        return -1;
    }
    strncpy (str_copy, bstr, len);

    LbsArray str_struct, *str = &str_struct;
    if (lbs_array_make_struct (str, sizeof (char), len, len, str_copy) == NULL)
    {
        free (str_copy);
        return -1;
    }

    if (lbs_array_append_data (&strv->array, &str_struct) < 0) {
        lbs_array_unref (str);
        free (str_copy);
        return -1;
    }

    return 0;
}

int lbs_strv_append_strv (LbsStrv* strv, const char* const* bstrv) {
    if (bstrv == NULL) {
        return -1;
    }

    int i;
    for (i = 0; bstrv[i] != NULL; i++) {
        if (lbs_strv_append_str (strv, bstrv[i]) < 0) {
            return -1;
        }
    }
    return 0;
}

int lbs_strv_remove_str (LbsStrv* strv) {
    size_t len = lbs_strv_get_len (strv);
    if (len <= 0) {
        return -1;
    }

    lbs_array_unref (lbs_strv_get_str_wrapper (strv, len - 1));
    return lbs_array_remove (&strv->array);
}

int lbs_strv_minimize (LbsStrv* strv) {
    if (lbs_array_minimize (&strv->array) < 0) {
        return -1;
    }

    size_t i;
    size_t len = lbs_strv_get_len (strv);
    for (i = 0; i < len; i++) {
        LbsArray* str = lbs_strv_get_str_wrapper (strv, i);
        if (lbs_array_minimize (str) < 0) {
            return -1;
        }
    }

    return 0;
}

char** lbs_strv_copy_strv (LbsStrv* strv) {
    size_t len = lbs_strv_get_len (strv);
    char** bstrv = xmalloc (sizeof (char*) * (len + 1));
    if (bstrv == NULL) {
        return NULL;
    }

    size_t i;
    for (i = 0; i < len; i++) {
        LbsArray* str = lbs_strv_get_str_wrapper (strv, i);
        size_t str_len = lbs_array_get_len (str);
        char* bstr = xmalloc (sizeof (char) * (str_len + 1));

        strncpy (bstr, lbs_array_get_data (str), str_len);
        bstr[str_len] = '\0';
        bstrv[i] = bstr;
    }
    bstrv[len] = NULL;
    return bstrv;
}

char** lbs_strv_drop_struct (LbsStrv* strv) {
    char** bstrv = lbs_strv_copy_strv (strv);
    if (bstrv == NULL) {
        return NULL;
    }

    lbs_strv_free (strv);
    return bstrv;
}

char** lbs_strv_generic_build (const char* str_first, ...) {
    LbsArray bstrv_w_struct, *bstrv_w = &bstrv_w_struct;
    va_list ap;
    char* str;
    char* str_copy;
    size_t str_len;

    if (lbs_array_init (bstrv_w, sizeof (void*)) < 0) {
        return NULL;
    }

    va_start (ap, str_first);

    str_len = strlen (str_first);
    str_copy = xmalloc (sizeof (char) * (str_len + 1));
    if (str_copy == NULL) {
        lbs_array_unref (bstrv_w);
        va_end (ap);
        return NULL;
    }
    strcpy (str_copy, str_first);

    if (lbs_array_append_ptr (bstrv_w, str_copy) < 0) {
        free (str_copy);
        lbs_array_unref (bstrv_w);
        va_end (ap);
        return NULL;
    }


    while ((str = va_arg (ap, char*)) != NULL) {
        str_len = strlen (str);
        str_copy = xmalloc (sizeof (char) * (str_len + 1));
        if (str_copy == NULL) {
            lbs_array_unref (bstrv_w);
            va_end (ap);
            return NULL;
        }
        strcpy (str_copy, str);

        if (lbs_array_append_ptr (bstrv_w, str_copy) < 0) {
            free (str_copy);
            lbs_array_unref (bstrv_w);
            va_end (ap);
            return NULL;
        }
    }
    if (lbs_array_append_ptr (bstrv_w, NULL) < 0) {
        lbs_array_unref (bstrv_w);
        va_end (ap);
        return NULL;
    }

    va_end (ap);

    return lbs_array_drop_struct (bstrv_w);
}

int lbs_strv_generic_cmp (
    const char* const* bstrv1, const char* const* bstrv2) {
    int i;
    for (i = 0; bstrv1[i] != NULL && bstrv2[i] != NULL; i++) {
        int r = strcmp (bstrv1[i], bstrv2[i]);
        if (r != 0) {
            return r;
        }
    }

    if (bstrv1[i] != NULL) {
        return 1;
    }
    if (bstrv2[i] != NULL) {
        return -1;
    }

    return 0;
}

void lbs_strv_generic_free (char** bstrv) {
    int i;
    for (i = 0; bstrv[i] != NULL; i++) {
        free (bstrv[i]);
    }
    free (bstrv);
}