/*
    Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file

    This file is part of 0MQ.

    0MQ is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    0MQ is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package zmq;

import java.nio.ByteBuffer;

public class Encoder extends EncoderBase
{
    private static final int SIZE_READY = 0;
    private static final int MESSAGE_READY = 1;

    private Msg inProgress;
    private final byte[] tmpbuf;
    private IMsgSource msgSource;

    public Encoder(int bufsize)
    {
        super(bufsize);
        tmpbuf = new byte[10];
        //  Write 0 bytes to the batch and go to messageReady state.
        nextStep((byte[]) null, 0, MESSAGE_READY, true);
    }

    @Override
    public void setMsgSource(IMsgSource msgSource)
    {
        this.msgSource = msgSource;
    }

    @Override
    protected boolean next()
    {
        switch(state()) {
        case SIZE_READY:
            return sizeReady();
        case MESSAGE_READY:
            return messageReady();
        default:
            return false;
        }
    }

    private boolean sizeReady()
    {
        //  Write message body into the buffer.
        nextStep(inProgress.data(), inProgress.size(),
                MESSAGE_READY, !inProgress.hasMore());
        return true;
    }

    private boolean messageReady()
    {
        //  Destroy content of the old message.
        //inProgress.close ();

        //  Read new message. If there is none, return false.
        //  Note that new state is set only if write is successful. That way
        //  unsuccessful write will cause retry on the next state machine
        //  invocation.

        if (msgSource == null) {
            return false;
        }

        inProgress = msgSource.pullMsg();
        if (inProgress == null) {
            return false;
        }

        //  Get the message size.
        int size = inProgress.size();

        //  Account for the 'flags' byte.
        size++;

        //  For messages less than 255 bytes long, write one byte of message size.
        //  For longer messages write 0xff escape character followed by 8-byte
        //  message size. In both cases 'flags' field follows.

        if (size < 255) {
            tmpbuf[0] = (byte) size;
            tmpbuf[1] = (byte) (inProgress.flags() & Msg.MORE);
            nextStep(tmpbuf, 2, SIZE_READY, false);
        }
        else {
            ByteBuffer b = ByteBuffer.wrap(tmpbuf);
            b.put((byte) 0xff);
            b.putLong(size);
            b.put((byte) (inProgress.flags() & Msg.MORE));
            nextStep(tmpbuf, 10, SIZE_READY, false);
        }

        return true;
    }
}

@@ -1746,31 +1746,11 @@
 ess.
-data(), inProgress.size
+buf
 (),%0A
@@ -3002,24 +3002,27 @@
       b.put(
+0, 
 (byte) 0xff)
@@ -3045,16 +3045,19 @@
 putLong(
+1, 
 size);%0A 
@@ -3073,16 +3073,19 @@
   b.put(
+9, 
 (byte) (
@@ -3142,18 +3142,9 @@
 tep(
-tmpbuf, 10
+b
 , SI

Use ByteBuffer to avoid copying when DirectByteBuffer or pos!=0 || limit != capacity