// -*- C++ -*-  vim: set syntax=cpp:
//
// (C) 2007 Frank-Rene Schaefer
// 
#ifndef __QUEX_INCLUDE_GUARD__BUFFER__MEMORY_POSITION_MIMIKER
#define __QUEX_INCLUDE_GUARD__BUFFER__MEMORY_POSITION_MIMIKER

QUEX_NAMESPACE_MAIN_OPEN
    /* DEBUG: 
    **
    ** The 'memory_position' type is a pointer mimiking class that stores also the
    ** **base position** of the buffer to which it referes. Locations are
    ** memory addresses. When a buffer-reload happens, those addresses have
    ** to be adapted. Imagine:
    **
    ** before:  
    **          Start                PosX                   Start = 0    
    **          |                    |                      PosX  = 21 
    **          [1234567890abcdfeghijklmnopqrstuvwxyzABC] 
    **
    **  after:
    **          Start    PosX                               Start = 13
    **          |        |                                  PosX  = 11 
    **          [cdfeghijklmnopqrstuvwxyzABCDEFGHIJKLMNO] 
    **
    ** -- If NDEBUG is not defined, this type is used, so that asserts in seek
    **    functions can check wether the start position refers to the current start
    **    position of the buffer (i.e. the memory_position has been updated).
    **
    ** -- If NDEBUG is defined, than this type is defined as a normal pointer to 
    **    the buffers character_type.
    **
    ** NOTE: This is only applied to the tell_adr() and seek_adr() functions.
    **       The lexeme start pointer is not effected, since it is entirely handled
    **       **inside** the buffer. Internal addresses **cannot** be considered
    **       as memory positions of this type, since they have to be adapted
    **       independently of the start position.
    **____________________________________________________________________________
    ** IMPORTANT: The one and only purpose of this class is to ensure that      **
    **            '+=' is called in the right manner, whenever a buffer         **
    **            reload has occured. IT CANNOT BE LINKED LOGICALLY TO THE      **
    **            OPERATORS +,-,++,--! DO NOT USE THIS TYPE EXCEPT FOR SIMPLE   **
    **            'TELL' AND 'SEEK'.                                            **
    */
    struct QUEX_NAME(MemoryPositionMimiker) {

        typedef size_t character_index; // Assume: The 'start position' is stored in
        //                              // terms of 'character index' rather the stream
        //                              // position. This is so, since some coding have
        //                              // a dynamically sized character encoding.

        // ALLOW: Only Adr, so that variable of type memory_position_mimiker can be
        //        can be initialized via a pointer, as a normal pointer does, e.g.
        //        "QUEX_TYPE_CHARACTER_POSITION last_acceptance_input_position = (QUEX_TYPE_CHARACTER*)(0x00);"
        QUEX_NAME(MemoryPositionMimiker)(QUEX_TYPE_CHARACTER* Adr=0x0, character_index Pos=0) 
            : address(Adr), buffer_start_position(Pos) {}

        QUEX_TYPE_CHARACTER*  address;
        character_index       buffer_start_position;

        bool operator==(const QUEX_NAME(MemoryPositionMimiker)& That)
        { 
          __quex_assert(this->buffer_start_position == That.buffer_start_position); 
          return this->address == That.address; 
        }
        bool operator!=(const QUEX_NAME(MemoryPositionMimiker)& That)
        { return ! (this->operator==(That)); }

        bool operator==(const QUEX_TYPE_CHARACTER* ThatAdr) { return this->address == ThatAdr; }
        bool operator!=(const QUEX_TYPE_CHARACTER* ThatAdr) { return this->address != ThatAdr; }

        // When loading forward from the stream, the pointers to memory_positions move backwards.
        // Thus, the signs in the operators are mirrored.
        // (operators not to be used in concatination -> void)
        void operator+=(const ptrdiff_t Value) { address += Value; buffer_start_position -= (character_index)Value; }
        void operator-=(const ptrdiff_t Value) { address -= Value; buffer_start_position += (character_index)Value; }

        // conversion operator, so that the object can be used at any place
        // where a normal provided_QUEX_TYPE_CHARACTER pointer is required (integrates seemingless)
        operator QUEX_TYPE_CHARACTER*() { return address; }
    };

QUEX_NAMESPACE_MAIN_CLOSE

#endif // __QUEX_INCLUDE_GUARD__BUFFER__MEMORY_POSITION_MIMIKER
