view rep/REPCommandPacker.java @ 500:66096af6a0e0

Added tag global-seq-sort for changeset 4bcc6b563d52
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 Oct 2010 11:23:21 +0900
parents f8916a96a373
children
line wrap: on
line source

package rep;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;

import rep.channel.REPPack;

/*
//+-------+--------+--------+-------+--------+---------+------+
//| cmd   | session| editor | seqid | lineno | textsiz | text |
//|       | id     | id     |       |        |         |      |
//+-------+--------+--------+-------+--------+---------+------+
//o-------header section (network order)-------------o
int cmd;	// command
int sid;	// session ID : uniqu to editing file
int eid;	// editor ID : owner editor ID = 1。Session に対して unique
int seqno;	// Sequence number : sequence number はエディタごとに管理
int lineno;	// line number
int textsize;   // textsize : bytesize
byte[] text;
*/


public class REPCommandPacker implements REPPack<REPCommand> {
	private static final int TEXTSIZELIMIT = 0x7000000;
	private static final int HEADER_SIZE = 24;
	// JIS/S-JIS = 2, UTF-8 = 3, UTF-?? = 5
	private static final int CHARSIZE = 5;

	Charset charset = Charset.forName("UTF-8");
	CharsetEncoder encoder = charset.newEncoder();
	CharsetDecoder decoder = charset.newDecoder();

	/* (non-Javadoc)
	 * @see rep.REPPack#packUConv(rep.REPCommand)
	 */
	public ByteBuffer packUConv(REPCommand command){
		int size = 0;
		if (command.string!=null) size = command.string.length()*CHARSIZE;
    	ByteBuffer buffer = ByteBuffer.allocateDirect(HEADER_SIZE+size);
    	buffer.clear();  // position = 0 
    	buffer.putInt(command.cmd.id);
    	buffer.putInt(command.sid);
    	buffer.putInt(command.eid);
    	buffer.putInt(command.seq);
    	buffer.putInt(command.lineno);     	
    	
    	int pos = buffer.position();
    	buffer.putInt(0);
    	int pos1 = buffer.position();

    	if (command.string!=null) {
    		//Encode to UTF8
    		CharBuffer cb = CharBuffer.wrap(command.string);
    		try {
    			encoder.encode(cb, buffer, true);
    		} catch (IllegalStateException e) {
    			buffer.position(pos1);
    		}
    	}
		
		//Encoded string length set
		int length = buffer.position() -pos1 ;
		buffer.putInt(pos, length);
		buffer.limit(HEADER_SIZE+length);
		buffer.rewind();
		
		return buffer;    	
	}


	public REPCommand unpackUConv(SocketChannel sc) throws IOException {
		ByteBuffer header = ByteBuffer.allocateDirect(HEADER_SIZE);
		header.clear();

		while(header.remaining()>0){
			if (sc.read(header)<0) throw new IOException();
		} 
		
		header.rewind();  // position = 0

		int cmd = header.getInt();
		int sid = header.getInt();
		int eid = header.getInt();
		int seqid = header.getInt();
		int lineno = header.getInt();
		int textsiz = header.getInt();

		/**
		 * We should avoid large reading here. Large command should be
		 * broke in smaller one. It should be easy.
		 */
		if (textsiz>TEXTSIZELIMIT||textsiz<0) {
			// corrupted packet
			throw new IOException();
		}
		ByteBuffer textBuffer = ByteBuffer.allocateDirect(textsiz);

		while(textBuffer.remaining()>0){
			if (sc.read(textBuffer)<0) throw new IOException();
		}
		textBuffer.rewind();

		//Decode UTF-8 to System Encoding(UTF-16) 
		String string;
		try {
			CharBuffer cb;
			cb = decoder.decode(textBuffer);
			cb.rewind();
			string = cb.toString();
		} catch (CharacterCodingException e) {
			string = "";
		}
		textsiz = string.length();
		REPCommand repcommand = new REPCommand(cmd, sid, eid, seqid, lineno, textsiz, string);
		//if (isLogging)
		//System.out.println("Reading: "+repcommand);
		return repcommand;		
	}

}