⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 faststreamreader.java

📁 src版Buffalo最新框架
💻 JAVA
字号:
/*
 * Copyright 2002-2004 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * $Id: FastStreamReader.java,v 1.1 2006/10/01 13:58:22 mechiland Exp $
 */
package net.buffalo.protocal.io;

import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.Stack;

import net.buffalo.protocal.ProtocalTag;
import net.buffalo.protocal.ProtocolException;

public class FastStreamReader implements StreamReader {

	public final static int TAG_EOF = -1;
	public final static int TAG_NULL = 0;
	public final static int TAG_BOOLEAN = 1;
	public final static int TAG_INT = 2;
	public final static int TAG_LONG = 3;
	public final static int TAG_DOUBLE = 4;
	public final static int TAG_DATE = 5;
	public final static int TAG_STRING = 6;
	public final static int TAG_MAP = 9;
	public final static int TAG_LIST = 10;
	public final static int TAG_TYPE = 11;
	public final static int TAG_LENGTH = 12;
	public final static int TAG_REF = 13;
	public final static int TAG_CALL = 15;
	public final static int TAG_FAULT = 17;
	public final static int TAG_METHOD = 18;
	public final static int TAG_NULL_END = TAG_NULL + 100;
	public final static int TAG_BOOLEAN_END = TAG_BOOLEAN + 100;
	public final static int TAG_INT_END = TAG_INT + 100;
	public final static int TAG_LONG_END = TAG_LONG + 100;
	public final static int TAG_DOUBLE_END = TAG_DOUBLE + 100;
	public final static int TAG_DATE_END = TAG_DATE + 100;
	public final static int TAG_STRING_END = TAG_STRING + 100;
	public final static int TAG_MAP_END = TAG_MAP + 100;
	public final static int TAG_LIST_END = TAG_LIST + 100;
	public final static int TAG_TYPE_END = TAG_TYPE + 100;
	public final static int TAG_LENGTH_END = TAG_LENGTH + 100;
	public final static int TAG_REF_END = TAG_REF + 100;
	public final static int TAG_CALL_END = TAG_CALL + 100;
	public final static int TAG_FAULT_END = TAG_FAULT + 100;
	public final static int TAG_METHOD_END = TAG_METHOD + 100;

	protected static HashMap tagCache;
	protected int peek;
	protected int peekTag;
	protected StringBuffer sbuf = new StringBuffer();
	protected StringBuffer entityBuffer = new StringBuffer();
	
	private final Reader in;
	
	protected Stack stack  = new Stack();
	
	protected int depth = 0;
	
	protected Tag currentTag;
	
	protected FastStreamReader() {
		this.in = null;
	}
	
	public FastStreamReader(Reader in) {
		this.in = in;
	    peek = -1;
	    peekTag = -1;
		moveDown();
	}

	public void close() {
		try {
			in.close();
		} catch (IOException e) {
			throw new StreamException(e);
		}
	}

	public String getNodeName() {
		return tagName(currentTag.tag);
	}

	public String getValue() {
		return currentTag.value;
	}

	public boolean hasMoreChildren() {
		int tag = parseTag();
		peekTag = tag;
		return 0 < tag && tag <100;
	}

	public void moveDown() {
		
		int tag = parseTag();
		switch(tag) {
		case TAG_METHOD:
		case TAG_INT:
		case TAG_LENGTH:
		case TAG_TYPE:
		case TAG_STRING:
		case TAG_BOOLEAN:
		case TAG_LONG:
		case TAG_DATE:
		case TAG_DOUBLE:
		case TAG_NULL:
		case TAG_REF:
		case TAG_LIST:
		case TAG_MAP:
		case TAG_CALL: 
			currentTag = new Tag(tag, parseString());
			stack.push(currentTag);
			depth++;
			break;
			
		default: throw new ProtocolException("unexpected tag: " + tagName(tag));
		}
	}
	
	public void moveUp() {
		int tag = parseTag();
		currentTag = (Tag) stack.pop();
		if (currentTag.tag+100 == tag) {
			depth--;
			currentTag = (Tag) stack.get(depth-1);
		} else {
			throw new ProtocolException("tag not match: " + tagName(currentTag.tag));
		}
	}

	protected String parseString() {
		sbuf.setLength(0);
		int ch;
		while ((ch = readChar()) >= 0)
			sbuf.append((char) ch);
		return sbuf.toString();
	}

	private int readChar() {
		int ch = read();
		if (ch == '<' || ch < 0) {
			peek = ch;
			return -1;
		}

		if (ch == '&') {
			ch = read();
			if (ch == '#') {
				ch = read();
				if (ch >= '0' && ch <= '9') {
					int v = 0;
					for (; ch >= '0' && ch <= '9'; ch = read()) {
						v = 10 * v + ch - '0';
					}

					if (ch != ';')
						throw new ProtocolException("expected ';' at " + (char) ch);

					return (char) v;
				} else
					throw new ProtocolException("expected digit at " + (char) ch);
			} else {
				entityBuffer.setLength(0);
				for (; ch >= 'a' && ch <= 'z'; ch = read())
					entityBuffer.append((char) ch);

				String entity = entityBuffer.toString();

				if (ch != ';')
					throw expectedChar("';'", ch);

				if (entity.equals("amp"))
					return '&';
				else if (entity.equals("apos"))
					return '\'';
				else if (entity.equals("quot"))
					return '"';
				else if (entity.equals("lt"))
					return '<';
				else if (entity.equals("gt"))
					return '>';
				else
					throw new ProtocolException("unknown XML entity &"
							+ entity + "; at `" + (char) ch + "'");
			}
		} else if (ch < 0x80)
			return (char) ch;
		else if ((ch & 0xe0) == 0xc0) {
			int ch1 = read();
			int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f);

			return (char) v;
		} else if ((ch & 0xf0) == 0xe0) {
			int ch1 = read();
			int ch2 = read();
			int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f);
			return (char) v;
		} else
			throw new ProtocolException("bad utf-8 encoding");
	}
	
	protected static String tagName(int tag)
	  {
	    switch (tag) {
	    case TAG_NULL: return "null";
	    case TAG_BOOLEAN: return "boolean";
	    case TAG_INT: return "int";
	    case TAG_LONG: return "long";
	    case TAG_DOUBLE: return "double";
	    case TAG_STRING: return "string";
	    case TAG_MAP: return "map";
	    case TAG_LIST: return "list";
	    case TAG_TYPE: return "type";
	    case TAG_LENGTH: return "length";
	    case TAG_REF: return "ref";
	    case TAG_CALL: return "buffalo-call";
	    case TAG_FAULT: return "fault";
	    case TAG_METHOD: return "method";
	    case TAG_DATE: return "date";
	    case -1: return "end of file";
	    default: return "unknown " + tag;
	    }
	}
	
	private int parseTag() {
		if (peekTag >= 0) {
			int tag = peekTag;
			peekTag = -1;
			return tag;
		}
		int ch = skipWhitespace();
		int endTagDelta = 0;
		if (ch != '<') throw expectedChar("'<'", ch);
		ch = read(); 
		if (ch == '/') {
			endTagDelta = 100;
			try {
				ch = readSingleChar();
			} catch (IOException e) {
				throw new StreamException(e);
			}
		}

		if (!isTagChar(ch)) throw expectedChar("tag", ch);
		sbuf.setLength(0);
		for (; isTagChar(ch); ch = read()) sbuf.append((char) ch);
		if (ch != '>') throw expectedChar("'>'", ch); 
		Integer value = (Integer) tagCache.get(sbuf.toString());
		if (value == null) throw new ProtocolException("Unknown tag <" + sbuf + ">");

		return value.intValue() + endTagDelta;
	}

	protected int readSingleChar() throws IOException {
		return in.read();
	}

	private boolean isTagChar(int ch) {
		return (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0'
				&& ch <= '9' || ch == ':' || ch == '-');
	}
	
	private int skipWhitespace() {
		int ch = read();
		for (; ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; ch = read()) {}
		return ch;
	}

	private int read() {
		if (peek >= 0) {
			int value = peek;
			peek = -1;
			return value;
		}
		try {
			return readSingleChar();
		} catch (IOException e) {
			throw new StreamException(e);
		}
	}

	private ProtocolException expectedChar(String expect, int ch) {
		if (ch < 0)
			return new ProtocolException("expected " + expect + " at end of file");
		else
			return new ProtocolException("expected " + expect + " at " + (char) ch);
	}

	static {
		tagCache = new HashMap();
		tagCache.put(ProtocalTag.TAG_NULL, new Integer(TAG_NULL));
		tagCache.put(ProtocalTag.TAG_BOOLEAN, new Integer(TAG_BOOLEAN));
		tagCache.put(ProtocalTag.TAG_INT, new Integer(TAG_INT));
		tagCache.put(ProtocalTag.TAG_LONG, new Integer(TAG_LONG));
		tagCache.put(ProtocalTag.TAG_DOUBLE, new Integer(TAG_DOUBLE));
		tagCache.put(ProtocalTag.TAG_DATE, new Integer(TAG_DATE));
		tagCache.put(ProtocalTag.TAG_STRING, new Integer(TAG_STRING));
		tagCache.put(ProtocalTag.TAG_MAP, new Integer(TAG_MAP));
		tagCache.put(ProtocalTag.TAG_LIST, new Integer(TAG_LIST));
		tagCache.put(ProtocalTag.TAG_TYPE, new Integer(TAG_TYPE));
		tagCache.put(ProtocalTag.TAG_LENGTH, new Integer(TAG_LENGTH));
		tagCache.put(ProtocalTag.TAG_REF, new Integer(TAG_REF));
		tagCache.put(ProtocalTag.TAG_CALL, new Integer(TAG_CALL));
		tagCache.put(ProtocalTag.TAG_FAULT, new Integer(TAG_FAULT));
		tagCache.put(ProtocalTag.TAG_METHOD, new Integer(TAG_METHOD));
	}
	
	class Tag {
		protected final int tag;
		protected final String value;
		public Tag(int tag, String value) {
			this.tag = tag;
			this.value = value;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -