#define XERR "memorybuf"
#include "memorybuf.ih"

    // called when using e.g., sharedstreamobj << file.rdbuf()

// overrides
streamsize MemoryBuf::xsputn(char const *buf, streamsize nChars)
{
    size_t toWrite = nChars;
    size_t nWritten = 0;

    size_t offset = d_bridge.offset();
    size_t avail = epptr() - pptr();            // available buffer space

    while (toWrite)
    {
        if (avail == 0)                         // no space: try to reload
        {                                       // the buffer
            if (overflow(*buf) == EOF)          // storage space exhausted?
                break;                          // yes: done

            ++buf;                              // no: 1 byte was written
            ++nWritten;
            ++offset;

            --toWrite;

            avail = epptr() - pptr();           // remaining buffer space

            if (avail == 0)                     // next cycle if avail == 0
                continue;
        }

        size_t next = min(avail, toWrite);      // next #bytes to write

        memcpy(pptr(), buf, next);              // write to the buffer

        pbump(next);                            // update pptr

        buf += next;                            // update pos & counters
        nWritten += next;
        toWrite -= next;
        d_bridge.offset(offset += next);

        avail -= next;
    }

//xerr("wrote " << nWritten);

    d_bridge.writtenUntil(offset);              // maybe enlarge the reading
                                                // area

    d_last = WRITE;                             // now in the WRITE state

    return nWritten;
}


// xerr("1 - begin: " << d_bridge.blockBegin() << 
//     ", offset: " << offset << 
//     ", end: " << d_bridge.blockEnd() <<
//     ", avail = " << avail << 
//     ", toWrite: " << toWrite);
// 
// xerr("2 -  after overflow. begin: " << d_bridge.blockBegin() << 
//      ", offset: " << offset << 
//      ", end: " << d_bridge.blockEnd() <<
//     ", avail: " << avail <<
//     ", toWrite: " << toWrite);
// 
// 
// xerr("3 - writing " << next << 
//         " to " << (void *)pptr() <<
//         " pbase: " << (void *)pbase() <<
//         " egptr: " << (void *)epptr()
// );
// 
// xerr("4 -  after memcpy. begin: " << d_bridge.blockBegin() << 
//      ", offset: " << offset << 
//      ", end: " << d_bridge.blockEnd() <<
//     ", avail: " << avail <<
//     ", toWrite: " << toWrite << "\n"
//     "                   to " << (void *)pptr() <<
//     " pbase: " << (void *)pbase() <<
//     " egptr: " << (void *)epptr()
// );
// 
// //cout << "...";
// //string line;
// //getline(cin, line);
// //if (not line.empty())
// //    throw 0;
// 
// 
// xerr("5 -  while ends. to write: " << toWrite <<
//     ", returning. begin: " << d_bridge.blockBegin() << 
//      ", offset: " << offset << 
//      ", end: " << d_bridge.blockEnd() <<
//     ", avail: " << avail <<
//     ", nWritten: " << nWritten);
// 
// xerr("5 -  returning. begin: " << d_bridge.blockBegin() << 
//      ", offset: " << offset << 
//      ", end: " << d_bridge.blockEnd() <<
//     ", avail: " << avail <<
//     ", nWritten: " << nWritten);
