Code review

 

Hello everyone,

I would like to ask for a code review of these three buffer implementations.

Main concern is performance and universality of the given code.

    ///////////////////////////////////////
    //
    //  First in Last out buffer
    //

        template <typename T>
        struct buffer_filo
        {
            private:
            
                // Internal state
                int     _size;
                int     _ptr;
    
                // Buffer
                T       buffer[];

                        
            public:

                // Constructor
                buffer_filo() :
                    _size(NULL),
                    _ptr(-1)
                { };
            
                // reset
                void reset() 
                { 
                    ArrayFree(buffer); 
                    _size = NULL; 
                    _ptr = -1; 
                };
                
                // Size
                int size() const
                { return(_ptr + 1); };
                
                // Push new element
                bool push(const T p_in)
                {
                    _ptr            = (_ptr == _size - 1) ? ArrayResize(buffer, _size + 1, (_size < 512) ? 1024 : (_size >> 1)) - 1 : (_ptr + 1); 
                    _size          += (_ptr == _size);
                    buffer[_ptr]    = p_in; 
                    return(_ptr >= NULL);
                };

                // Pop last element
                T pop()
                { return((_ptr < NULL) ? _ptr : buffer[_ptr--]); };
                
                // Access operator
                T operator[](const int idx) const
                { return(buffer[idx]); }
        };



    ///////////////////////////////////////
    //
    //  First In First Out buffer
    //

                template <typename T>
        struct buffer_fifo
        {
            private:
            
                // Internal state
                uint    pop_buffer;
                uint    pop_ptr;
                bool    push_buffer;
                uint    push_ptr;
                uint    buffer_1_end;
                uint    buffer_1_size;
                uint    buffer_2_end;
                uint    buffer_2_size;
                uint    element_cnt;
                uint    pre_allocate;

                T       _empty;
    
                // Buffer
                T       buffer_1[];
                T       buffer_2[];


            public:

                // Constructor

                    buffer_fifo() :
                        pop_buffer      (0x01),
                        pop_ptr         (NULL),
                        
                        push_buffer     (false),
                        push_ptr        (NULL),
                        
                        buffer_1_end    (NULL),
                        buffer_1_size   (NULL),
                        
                        buffer_2_end    (NULL),
                        buffer_2_size   (NULL),
    
                        element_cnt     (NULL),
                        pre_allocate    (4096 / sizeof(T))
                    { ZeroMemory(_empty); };

            
                // Reset

                    void reset() 
                    { 
                        ArrayResize(buffer_1, NULL, pre_allocate);
                        ArrayResize(buffer_1, NULL, pre_allocate);
                        pop_buffer      = 0x01;
                        pop_ptr         = NULL;
                        push_buffer     = false;
                        push_ptr        = NULL;
                        buffer_1_end    = NULL;
                        buffer_1_size   = NULL;
                        buffer_2_end    = NULL;
                        buffer_2_size   = NULL;
                        element_cnt     = NULL;
                    };
                

                // Size

                    int size() const
                    { return((int)(element_cnt - (element_cnt > NULL))); };

                
                // Push new element

                    void push(const T p_in)
                    { 
                        const bool buffer_change = ((!(pop_buffer == 0x01) == push_buffer) && (pop_ptr > NULL));
                        push_buffer = (buffer_change) ? !push_buffer : push_buffer;
                        push_ptr    = (buffer_change) ? NULL : push_ptr;
    
                        element_cnt += 1 + (element_cnt == NULL);
                        if(push_buffer)
                        {
                            buffer_2_size = (buffer_2_size > push_ptr) ? buffer_2_size : ArrayResize(buffer_2, buffer_2_size + 1, (pre_allocate > (buffer_2_size >> 1)) ? pre_allocate : buffer_2_size >> 1);
                            buffer_2[push_ptr++] = p_in;
                            buffer_2_end = push_ptr;
                            return;
                        }
    
                        buffer_1_size = (buffer_1_size > push_ptr) ? buffer_1_size : ArrayResize(buffer_1, buffer_1_size + 1, (pre_allocate > (buffer_1_size >> 1)) ? pre_allocate : buffer_1_size >> 1);
                        buffer_1[push_ptr++] = p_in;
                        buffer_1_end = push_ptr;
                        return;
                    };


                // Pop oldest element

                    T pop()
                    {
                        // Switch buffer
                        switch(pop_buffer * (element_cnt != NULL))
                        {
                            case 0x00:
                                return(_empty);

                            case 0x01:
                                pop_buffer  = (pop_ptr == buffer_1_end) ? 0x02 : 0x01;
                                pop_ptr     = (pop_ptr == buffer_1_end) ? NULL : pop_ptr;
                                break;
                                
                            case 0x02:
                                pop_buffer  = (pop_ptr == buffer_2_end) ? 0x01 : 0x02;
                                pop_ptr     = (pop_ptr == buffer_2_end) ? NULL : pop_ptr;
                                break;
                        }
    
                        // Element counter
                        element_cnt -= (1 + (element_cnt == 2));
    
                        // Return
                        switch(pop_buffer)
                        {
                            case 0x01:
                                return(buffer_1[pop_ptr++]);
    
                            case 0x02:
                                return(buffer_2[pop_ptr++]);
                        }
    
                        // Return
                        return(_empty);
                    };


                // Access operator

                    T operator[](const uint idx) const
                    {  
                        uint cnt_buffer = NULL;
                        switch(pop_buffer * ((element_cnt != NULL) && ((element_cnt - 1) > idx)))
                        {
                            case 0x01:
                                cnt_buffer = buffer_1_end - pop_ptr;
                                if(idx < cnt_buffer)
                                { return(buffer_1[pop_ptr + idx]); }
                                return(buffer_2[idx - cnt_buffer]);
                                
                            case 0x02:
                                cnt_buffer = buffer_2_end - pop_ptr;
                                if(idx < cnt_buffer)
                                { return(buffer_2[pop_ptr + idx]); }
                                return(buffer_1[idx - cnt_buffer]);
                        }
                        
                        return(_empty); 
                    };
        };



    ///////////////////////////////////////
    //
    //  Circle buffer
    //

        template <typename T>
        struct buffer_circle : public buffer_fifo<T>
        {
            private:
                
                // Internal state
                uint _max_size;
                

            // Default constructor
            public:

                buffer_circle() :
                    buffer_fifo(),
                    _max_size   (NULL)
                { };


            // Overwritte size function
            int size(const int max_size = -1)
            {
                switch(max_size)
                {
                    case -1:
                        return(buffer_fifo<T>::size());
                    case 0x00:
                        _max_size = NULL;
                        buffer_fifo<T>::reset();
                        return(NULL);
                }

                while(buffer_fifo<T>::size() > max_size)
                { pop(); }

                _max_size = max_size;
                return(buffer_fifo<T>::size());
            }

            
            // Overwritten push function
            void push(const T p_in)
            {
                if(buffer_fifo<T>::size() >= (int)_max_size)
                { pop(); }
                buffer_fifo<T>::push(p_in);
            }
        };

I would be thankful for any improvements and suggestions to above code.