aboutsummaryrefslogblamecommitdiffstats
path: root/l4array.c
blob: fed2876e97a7c8021eafb051b0253727265485b1 (plain) (tree)
1
2
3
4
5
6
7
8
9

                    

                   
 

                                                            

                            


                                                     

                            




                                                 

                                    


                                   
         
 







                                

 


                                                                        
         
 



                                                 
                 


                                   
         







                                


                 








                                                                              
                 
         




                                                             

 


                                                                
         


                                       
         







                                                                                 

 





                                                    
         



















                                                               
                 
         



                              
 
 







                                               

 











                                                          
         
















                                                         
         
                 
 
 



                                                             
         



                          

 














                                                                            
         







                                                                     

                          




                                           


                 




                                                                            
                 

                                        
         
                 
 
#include "l4array.h"

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

LbsArray* lbs_array_new_with_max (size_t size, size_t max) {
    if (size <= 0) {
        return NULL;
    }

    LbsArray* array = malloc (sizeof (LbsArray));
    if (array == NULL) {
        return NULL;
    }

    if (max > 0) {
        void* data = malloc (size * max);
        if (data == NULL) {
            free (array);
            return NULL;
        }
        array->data = data;
    } else {
        array->data = NULL;
    }

    array->free_func = NULL;
    array->size = size;
    array->len = max;
    array->max = max;
    array->ref_count = 1;
    array->is_alloc = true;

    return array;
}

int lbs_array_init_with_max (LbsArray* array, size_t size, size_t max) {
    if (size <= 0) {
        return -1;
    }

    if (max > 0) {
        void* data = malloc (size * max);
        if (data == NULL) {
            return -1;
        }
        array->data = data;
    } else {
        array->data = NULL;
    }

    array->free_func = NULL;
    array->size = size;
    array->len = max;
    array->max = max;
    array->ref_count = 1;
    array->is_alloc = false;

    return 0;
}

LbsArray* lbs_array_copy (LbsArray* dest, const LbsArray* src) {
    if (dest == NULL) {
        dest = lbs_array_new_with_max (src->size, src->max);
        if (dest == NULL) {
            return NULL;
        }
    } else {
        if (lbs_array_init_with_max (dest, src->size, src->max) < 0) {
            return NULL;
        }
    }

    dest->len = src->len;
    dest->free_func = src->free_func;
    memcpy (dest->data, src->data, src->size * src->len);
    return dest;
}

LbsArray* lbs_array_cat (LbsArray* dest, const LbsArray* more) {
    if (dest == NULL) {
        return lbs_array_copy (dest, more);
    }

    if (dest->size != more->size) {
        return NULL;
    }

    int oldlen = dest->len;
    if (lbs_array_set_len (dest, dest->len + more->len) < 0) {
        return NULL;
    }

    memcpy (lbs_array_vp (dest, oldlen), more->data, more->size * more->len);
    return dest;
}

void* lbs_array_ref_generic (void* array_generic) {
    LbsArray* array = LBS_ARRAY (array_generic);
    int oldref = array->ref_count;
    int newref = oldref + 1;
    if (newref <= oldref) {
        return NULL;
    }

    array->ref_count = newref;
    return array;
}

void lbs_array_unref_generic (void* array_generic) {
    LbsArray* array = LBS_ARRAY (array_generic);
    array->ref_count--;
    if (array->ref_count <= 0) {
        lbs_array_free (array);
    }
}

void lbs_array_free_generic (void* array_generic) {
    LbsArray* array = LBS_ARRAY (array_generic);
    if (array->free_func != NULL) {
        int i = 0;
        char* d = array->data;
        for (; i < array->len; i++, d += array->size) {
            (*(array->free_func)) (*((void**)d));
        }
    }
    free (array->data);
    if (array->is_alloc) {
        free (array);
    }
}

void* lbs_array_drop_struct (LbsArray* array) {
    if (!array->is_alloc) {
        return array->data;
    }

    void* data = array->data;
    free (array);
    return data;
}

LbsArray* lbs_array_make_struct (LbsArray* array,
    size_t size, size_t len, size_t max, void* data) {

    if (array == NULL) {
        array = lbs_array_new (size);
        if (array == NULL) {
            return NULL;
        }
    } else {
        if (lbs_array_init (array, size) < 0) {
            return NULL;
        }
    }

    array->len = len;
    array->max = max;
    array->data = data;
    return array;
}

int lbs_array_set_len (LbsArray* array, size_t len) {
    if (len > (array->max)){
        if (lbs_array_set_max (array, len) < 0) {
            return -1;
        } else {
            array->len = len;
        }
    } else {
        array->len = len;
        return 0;
    }
    return 0;
}

int lbs_array_set_max (LbsArray* array, size_t max) {
    void* ptr = realloc (array->data, array->size * max);
    if (ptr == NULL) {
        return -1;
    }

    array->max = max;
    array->data = ptr;
    return 0;
}

int lbs_array_append_ptr (LbsArray* array, const void* ptr) {
    return lbs_array_append_data (array, &ptr);
}

int lbs_array_append_data (LbsArray* array, const void* data) {
    if (array->max < array->len + 1) {
        if (array->max > 0){
            if (lbs_array_set_max (array, array->max * 2) < 0) {
                return -1;
            }
        } else {
            if (lbs_array_set_max (array, 1) < 0){
                return -1;
            }
        }
    }

    memcpy (lbs_array_vp (array, array->len), data, array->size);
    array->len++;
    return 0;
}

int lbs_array_remove (LbsArray* array) {
    if (array->len <= 0) {
        return -1;
    }

    array->len--;
    if (array->len < array->max * 2) {
        lbs_array_minimize (array);
    }
    return 0;
}

int lbs_array_minimize (LbsArray* array) {
    if (array->max > array->len) {
        void* ptr = realloc (array->data, array->size * array->len);
        if (ptr == NULL) {
            return -1;
        }
        array->max = array->len;
        array->data = ptr;
    }
    return 0;
}