#ifndef INCLUDED_BOBCAT_MEMORYBUF_
#define INCLUDED_BOBCAT_MEMORYBUF_

#include <ios>
#include <iosfwd>
#include <streambuf>

#include <bobcat/memorybridge>

namespace FBB
{
                                        // in memorybridge/memorybridge
class MemoryBuf: public std::streambuf
{
    enum Last
    {
        SEEK,
        READ,
        WRITE
    };

    Last d_last;                    // last requested action

    std::ios::openmode d_mode;

    MemoryBridge d_bridge;

    public:
        MemoryBuf();                                                    // 1

        MemoryBuf(MemoryBuf &&tmp);                                     // 2


        MemoryBuf(std::string const &bufSize, bool erase,              // 3
                std::ios::openmode openMode = std::ios::in | std::ios::out,
                size_t access = 0600);

        MemoryBuf(std::string const &bufSize,                           // .f
                std::ios::openmode openMode = std::ios::in | std::ios::out,
                size_t access = 0600);

        MemoryBuf(int id, bool erase,                                  // 4
                std::ios::openmode openMode = std::ios::in | std::ios::out);

        MemoryBuf(int id,                                               // .f
                std::ios::openmode openMode = std::ios::in | std::ios::out);

        ~MemoryBuf() override;

        MemoryBuf &operator=(MemoryBuf &&tmp);

        int id() const;                 // id of the shared Memory segment .f

        void info(std::ostream &out) const;                             // .f

        std::streamsize maxEnd() const;                                 // .f

        void setErase(bool erase);                                    // .f

        void swap(MemoryBuf &other);                                    // .f

        void truncate(std::streamsize size);                            // .f
        std::streamsize writtenUntil() const;                           // .f


    private:
        void noBuffers();
        std::streamsize getOffset();

        // all remaining members override

        int pbackfail(int ch)       override;
        std::streamsize showmanyc() override;

        int underflow()             override;
        int overflow(int ch)        override;

        std::streamsize xsgetn(char *buf, std::streamsize n)        override;
        std::streamsize xsputn(char const *buf, std::streamsize n)  override;

        std::ios::pos_type seekoff(
            std::ios::off_type offset,
            std::ios::seekdir way = std::ios::beg,
            std::ios::openmode mode = std::ios::in | std::ios::out) override;
    
        std::ios::pos_type seekpos(
            std::ios::pos_type offset,
            std::ios::openmode mode = std::ios::in | std::ios::out) override;

};

#include "memorybuf.f"

} // FBB

#endif
