Source

Chain / chain.h

/*    
    Chains: Native dynamic arrays for any type of variable in a convenient 
              package (.c/.h)

    Copyright (C) 2012  Sulaiman A. Mustafa
    
    [ Alternative licensing is available ]
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
    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. 
    
    Contact me if an alternative license is desired. Depending on the type of 
    intended use, an alternative license might be granted free of charge, in 
    exchange for compensation, or it might not be granted at all.
    
    Contact: http://people.sigh.asia/~sulaiman/about/contact/
    

            -----------------------------------------------------
            
توثيق المكتبة
-------------


    تصريف المكتبة
    -------------
    
    تعتمد المكتبة على بعض مزايا C99. مرر الخيار -std=c99 أو -std=gnu99
    لتصريف المكتبة على مصرف gcc أو clang.
    
    قد تتمكن من تصريفها وفق معيار أقدم باستخدام إضافات مثل gnu89.
    

    قواعد عامة لاستخدام المكتبة
    --------------------------
    
    فيما يلي قواعد عامة لاستخدام قوالب هذه المكتبة. أغلب هذه القواعد 
    تكرار للقواعد العامة لتعامل مع قوالب السي، غير أن بعضها خاص 
    بهذه المكتبة.

        1. تذكر أن ما تستخدمه قوالب وليست دوالا.
        
        2. لا تمرر القوالب كمدخلات للدوال، ولا تستخدمها في العبارات بشكل عام
           إلا إن تكون القوالب مصصمة لذلك، وتصنف بـ"Reterns".
        
        3. لا تمرر مدخلات ذات آثار جانبية لاحتمال تكرر ورود المدخل في أثر من
           موقع بالقالب.
        
        4. أحط المصفوفات من الجنس `(type[]){ m, m, m}` المعرفة في منطقة 
           مدخلات القوالب بأقواس إضافية.
        

    
    التعامل مع الأخطاء
    -----------------
    
    للمكتبة دالة خاصة تنفذ عندما يحدث خطأ أو خلل أثناء تنفيذ أحدى دوالها 
    اسمها `chain_error'. 
    
    يمكنك إبدالها بدالة أخرى تقوم مقامها بتخزين عنوان الدالة الجديدة فيها
    مباشرة:
    
    chain_error=other_error_handling_func;
    
    على أن تكون صيغة الدالة كما يلي:
    
    void* other_error_handling_func()
    
    
    
    توثيق القوالب والدوال
    ---------------------
    
    (كتب التوثيق باللغة الإنجليزية لكثرة المصطلاحات التقنية)
    
#define chain_len(chain)
    
        Description: Returns the length of the chain.
        
        Attributes: No side-effects, Returns, functionless
        
        Arguments:      chain    a pointer to an array 
                                 returned by chain_new 
                                 or equivalent.
    
        Returns: The length of type `unint32_t'
        


#define chain_new(cell_type)
        
        Description: Generates a new empty array of type 
                     `cell_type' and returns a pointer to
                     it.
        
        Attributes: No side-effects, Returns
        
        Arguments:      cell_type   The type of elements 
                                    that are to be stored 
                                    in the new array.
        
        Returns: A pointer of type `*cell_type'
        

        
#define chain_shove(chain, what)
        
        Description: inserts an element at the beginning 
                     of a chain array.
        
        Attributes: Returns
        
        Arguments:      chain       A pointer to an array
                                    returned by chain_new
                                    or equivalent.
                                    
                        what        the element to be 
                                    inserted.
        
        Returns: the element to be inserted
        


#define chain_push(chain, what)
        
        Description: inserts an element at the end of a 
                     chain array.
        
        Attributes: Returns
        
        Arguments:      chain       A pointer to an array
                                    returned by chain_new
                                    or equivalent.
                                    
                        what        the element to be 
                                    inserted.
        
        Returns: the element to be inserted        



#define chain_insert(chain, where, what)
        
        Description: inserts an element at an arbitrary 
                     position in a chain array.
        
        Attributes: Returns
        
        Arguments:      chain       A pointer to an array
                                    returned by chain_new
                                    or equivalent.
                                    
                        where       The index at which 
                                    `what' should be 
                                    inserted.
                                    
                        what        The element to be 
                                    inserted.
        
        Returns: the element to be inserted
        


#define chain_remove(chain, where)
        
        Description: Removes an element from an array
        
        Attributes: None
        
        Arguments:      chain       A pointer to an array
                                    returned by chain_new
                                    or equivalent.
                                    
                        where       Index of the element 
                                    that should be removed        



#define chain_pop(chain)
        
        Description: Removes the last element of an array
                     and returns it.
        
        Attributes: Returns
        
        Arguments:      chain       A pointer to an array
                                    returned by chain_new
                                    or equivalent.
                       
        Returns: The element that was removed



#define chain_insert_all(chain, where, what, length)
        
        Description: inserts an array in another array
        
        Attributes: none
        
        Arguments:      chain       A pointer to an array
                                    returned by chain_new
                                    or equivalent.
                                    
                        where       The index at which the
                                    input array should be 
                                    inserted.
                                    
                        what        the input array that
                                    should be inserted.
                                    
                        length      The length of `what'
                                    
                       

#define chain_push_all(chain, what, length)
        
        Description: appends an array to another
        
        Attributes: none
        
        Arguments:      chain       A pointer to an array
                                    returned by chain_new
                                    or equivalent.
                                    
                        what        the input array that
                                    should be inserted.
                                    
                        length      The length of `what'
                                    
                       

#define chain_clip(chain, where)
        
        Description: clips the last part of an array
        
        Attributes: none
        
        Arguments:      chain       A pointer to an array
                                    returned by chain_new
                                    or equivalent.
                                    
                        where       the index at which 
                                    the array should be
                                    clipped. (inclusive)
                                    


*/





#ifndef SEIN_CHAIN
#define SEIN_CHAIN

#include <stdint.h>

/*fun fact: (({}), ...) seems like valid c99; check standard */

#define CHAIN_MTS    sizeof(uint32_t *)*2

#define chain_len(C) (*( ( (uint32_t *) (((void *)(C))-CHAIN_MTS) )+1 ))
#define chain_new(cell_type) (cell_type*) chain_new_(sizeof(cell_type))

#define chain_shove(C, what) ((C) = chain_resize_((C), 0, 1), (C)[0]=(what))
#define chain_insert(C, where, what) {unsigned int at = (where); ((C) = chain_resize_((C), at, 1), \
                                     (C)[(at>chain_len(C))?(chain_len(C)-1):at]=(what));}
#define chain_push(C, what) chain_insert((C), ~((uint32_t) 0), (what))

#define chain_remove(C, where) ((C)=chain_resize_((C), (where), -1))
#define chain_pop(C) (chain_remove((C), ~((uint32_t) 0)),(C)[chain_len(C)]=(C)[chain_len(C)])

#define chain_insert_all(C, where, what, length) ((C)=chain_insertm_((C), (where), (what), (length)))
#define chain_push_all(C, what, length) ((C)=chain_insertm_((C), ~((uint32_t) 0), (what), (length)))

#define chain_clip(C, where) ((C)=chain_clip_((C), (where)))


void* chain_new_(uint8_t size);
void* chain_resize_(void *c, uint32_t where, int8_t how);
void* chain_insertm_(void *c, uint32_t where, void *in, uint32_t len);
void* chain_clip_(void *c, uint32_t where);

void chain_free(void *c);

extern void (*chain_error)();

#endif