/* -*- C++ -*- vim: set syntax=cpp: */
#ifndef __QUEX_INCLUDE_GUARD__BUFFER__ASSERTS
#define __QUEX_INCLUDE_GUARD__BUFFER__ASSERTS

#ifndef QUEX_OPTION_ASSERTS

#    define QUEX_BUFFER_ASSERT_CONSISTENCY_LIGHT(B)    /* empty */
#    define QUEX_BUFFER_ASSERT_CONSISTENCY(B)          /* empty */
#    define QUEX_BUFFER_ASSERT_CONTENT_CONSISTENCY(B)  /* empty */
#    define QUEX_BUFFER_ASSERT_NO_BUFFER_LIMIT_CODE(Begin, End) /* empty */

#else
#    include <quex/code_base/definitions>
#    include <quex/code_base/buffer/Buffer>

QUEX_NAMESPACE_MAIN_OPEN

    /* NOTE: In some cases, we cannot make the assumption that the end of the content text
     *       is terminated by the buffer limit code. Skippers set the content of this cell
     *       temporarily to another value for the sake of speed efficiency. Thus, it is 
     *       distinguished between 'light' and normal consistency.                           */
    QUEX_INLINE void
    QUEX_BUFFER_ASSERT_CONSISTENCY_LIGHT(QUEX_NAME(Buffer)* B)                                      
    {                                                                                    
        __quex_assert( (B) != 0x0 );                                                     
        if( (*B)._memory._front != 0x0 || (*B)._memory._back != 0x0 ) {                    
            __quex_assert((*B)._memory._front < (*B)._memory._back);                     
            __quex_assert(*((*B)._memory._front) == QUEX_SETTING_BUFFER_LIMIT_CODE );    
            __quex_assert((*B)._input_p          >= (*B)._memory._front);                
            __quex_assert((*B)._lexeme_start_p   >= (*B)._memory._front);                

            if( (*B)._memory._end_of_file_p == 0x0 ) {                                           
                __quex_assert((*B)._input_p        <= (*B)._memory._back);               
                __quex_assert((*B)._lexeme_start_p <= (*B)._memory._back);               
            } else {                                                                     
                __quex_assert((*B)._input_p        <= (*B)._memory._end_of_file_p);              
                __quex_assert((*B)._lexeme_start_p <= (*B)._memory._end_of_file_p);              
                /**/                                                                     
                __quex_assert((*B)._memory._end_of_file_p  >= (*B)._memory._front + 1);          
                __quex_assert((*B)._memory._end_of_file_p  <= (*B)._memory._back);               
            }                                                                            
            __quex_assert(   (*B)._content_character_index_begin                         
                          <= (*B)._content_character_index_end    );                     
            if( ! (   (*B)._content_character_index_end   == (size_t)0                   
                      && (*B)._content_character_index_begin == (size_t)0 ) ) {             
                __quex_assert(   (size_t)(  (*B)._content_character_index_end            
                                            - (*B)._content_character_index_begin)         
                                 == (size_t)(  QUEX_NAME(Buffer_text_end)(B)                       
                                               - QUEX_NAME(Buffer_content_front)(B)));               
            }                                                                            
        }                                                                                
    }

    QUEX_INLINE void
    QUEX_BUFFER_ASSERT_CONSISTENCY(QUEX_NAME(Buffer)* B)                                            
    {                                                                                    
        QUEX_BUFFER_ASSERT_CONSISTENCY_LIGHT(B);                                              
        /* NOTE: No assumptions can be made in general on the relation between    */     
        /*       _input_p and _lexeme_start_p, since for forwards lexing          */     
        /*       _input_p comes before _lexeme_start_p, wherelse for back-        */     
        /*       ward lexing this is vice versa.                                  */     
        /*       See "code_base/core_engine/definitions-quex-buffer.h"            */     
        if( (*B)._memory._front != 0 || (*B)._memory._back != 0x0 ) {                    
            __quex_assert(*((*B)._memory._back) == QUEX_SETTING_BUFFER_LIMIT_CODE );    
            if( (*B)._memory._end_of_file_p != 0x0 ) {                                           
                __quex_assert(*(*B)._memory._end_of_file_p == QUEX_SETTING_BUFFER_LIMIT_CODE);   
            }                                                                            
        }                                                                                
    }

    QUEX_INLINE void
    QUEX_BUFFER_ASSERT_NO_BUFFER_LIMIT_CODE(QUEX_TYPE_CHARACTER* Begin, 
                                            QUEX_TYPE_CHARACTER* End)
    {
        QUEX_TYPE_CHARACTER* iterator = 0x0;
        __quex_assert(Begin <= End);

        for(iterator = Begin; iterator != End; ++iterator) {
            if( *iterator != QUEX_SETTING_BUFFER_LIMIT_CODE ) continue;

            if( iterator == Begin ) {
                QUEX_ERROR_EXIT("Buffer limit code character appeared as first character in buffer.\n"
                                "This is most probably a load failure.\n");
            } else {
                QUEX_ERROR_EXIT("Buffer limit code character appeared as normal text content.\n");
            }
        }
    }

    QUEX_INLINE void
    QUEX_BUFFER_ASSERT_CONTENT_CONSISTENCY(const QUEX_NAME(Buffer)* buffer)
    {
        QUEX_TYPE_CHARACTER* End = buffer->_memory._back;

        if( buffer->_memory._front == 0x0 && buffer->_memory._back == 0x0 ) return;
        if( buffer->_memory._end_of_file_p != 0x0 ) End = buffer->_memory._end_of_file_p;
        QUEX_BUFFER_ASSERT_NO_BUFFER_LIMIT_CODE(buffer->_memory._front + 1, End);
    }

QUEX_NAMESPACE_MAIN_CLOSE

#endif

#endif /* __QUEX_INCLUDE_GUARD__BUFFER__ASSERTS */
