📄 ubbdecoder.java
字号:
/**
*
*/
package util;
import java.util.*;
/**
* 版权所有 2006(C) 中国Java手机网(www.cnjm.net)。所有版权保留。
* 作者开放本代码的目的是希望更多人使用它,任何人只要遵从以下条款,就可以传播、使用或修改本代码:
* 1. 再发布本代码必须完整保留此版权声明及条款,不得删除。
* 2. 使用本代码开发的软件必须在版权信息中声明: “本软件在开发中使用了中国Java手机网(www.cnjm.net)编写的UBB转换引擎”。
* 3. 使用本代码开发的软件应在文档中加入中国Java手机网(www.cnjm.net)的链接。
* 4. 使用者必须独自承担使用本代码的风险,中国Java手机网不为本代码对其软件或系统可能造成的任何损害承担责任。
*/
public class UBBDecoder {
public static final int MODE_IGNORE = 0;
public static final int MODE_CLOSE = 1;
private static final int SEARCH_LEN = 200;
/**
* 进行UBB标签的转换
* @param s 需要转换的包含UBB标签的文本
* @param th 用户自定义的UBB标签的处理器的实例
* @param mode 容错模式,可以是忽略模式(MODE_IGNORE)或关闭模式(MODE_CLOSE)
* @return 转换后的包含HTML标签的文本
*/
public static final String decode(String s, UBBTagHandler th, int mode) {
return decode(s, th, mode, false);
}
/**
* 进行UBB标签的转换
* @param s 需要转换的包含UBB标签的文本
* @param th 用户自定义的UBB标签的处理器的实例
* @param mode 容错模式,可以是忽略模式(MODE_IGNORE)或关闭模式(MODE_CLOSE)
* @param convBr 是否把'\n'字符也转换为'<br>'
* @return 转换后的包含HTML标签的文本
*/
public static final String decode(String s, UBBTagHandler th, int mode, boolean convBr) {
StringBuffer buf = new StringBuffer();
char[] cc = s.toCharArray();
int len = cc.length, pos = 0;
UBBNode root = new UBBNode(null, "", null, "", false);
UBBNode node = root;
Stack stk = new Stack();
stk.push(node);
while (pos < len) {
char cur = cc[pos];
if (convBr && cur == '\n') {
buf.append("<br>");
pos++;
continue;
}
if (cur != '[') {
buf.append(cur);
pos++;
continue;
}
int ii = indexOf(cc, ']', pos + 1, SEARCH_LEN);
if (ii == -1) {
buf.append(cur);
pos++;
continue;
}
if (cc[pos + 1] == '/') { // tag starts with '/'
String tmp = new String(cc, pos + 2, ii - pos - 2).trim().toLowerCase();
int cnt = 1;
boolean find = false;
for (UBBNode nd = node; nd != null; nd = nd.parent, cnt++) {
if (nd.tag.equals(tmp)) {
find = true;
break;
}
}
if (find) {
addTextChild(node, buf);
while (cnt-- > 0) {
if (mode == MODE_CLOSE) {
node.closed = true;
}
node = (UBBNode) stk.pop();
}
node.closed = true;
node = node.parent;
pos = ii + 1;
continue;
} else {
buf.append("[/");
pos += 2;
continue;
}
} else if (cc[ii - 1] == '/') { // tag ends with '/'
String tmp = new String(cc, pos + 1, ii - pos - 2).trim();
String[] ss = th.parseTag(tmp, true);
if (ss != null && ss.length == 2) {
addTextChild(node, buf);
UBBNode nd = new UBBNode(node, ss[0].toLowerCase(), ss[1],
new String(cc, pos, ii + 1 - pos), true);
node.addChild(nd);
pos = ii + 1;
continue;
}
}
String tmp = new String(cc, pos + 1, ii - pos - 1).trim();
String[] ss = th.parseTag(tmp, false);
if (ss != null && ss.length == 2) {
addTextChild(node, buf);
UBBNode nd = new UBBNode(node, ss[0], ss[1],
new String(cc, pos, ii + 1 - pos), false);
node.addChild(nd);
pos = ii + 1;
stk.push(nd);
node = nd;
} else {
buf.append('[');
pos++;
}
}
addTextChild(node, buf);
// System.out.println("=========================\n" + root.toString(0));
return decodeNode(th, root);
}
private static void addTextChild(UBBNode node, StringBuffer buf) {
if (buf.length() > 0) {
node.addChild(new UBBNode(node, buf.toString()));
buf.setLength(0);
}
}
private static String decodeNode(UBBTagHandler th, UBBNode node) {
StringBuffer buf = new StringBuffer();
if (UBBNode.TEXT == node.tag) {
buf.append(node.img);
} else if (!node.closed) {
buf.append(node.img);
List lst = node.children;
if (lst != null && lst.size() > 0) {
for (int i = 0, n = lst.size(); i < n; i++) {
buf.append(decodeNode(th, (UBBNode) lst.get(i)));
}
}
} else {
List lst = node.children;
StringBuffer tmp = new StringBuffer();
if (lst != null && lst.size() > 0) {
for (int i = 0, n = lst.size(); i < n; i++) {
tmp.append(decodeNode(th, (UBBNode) lst.get(i)));
}
}
buf.append(th.compose(node.tag, node.attr, tmp.toString(), node.isEmpty));
}
return buf.toString();
}
private static final int indexOf(char[] cc, char c, int idx, int len) {
int end = idx + len;
if (end > cc.length) end = cc.length;
for (int i = idx; i < end; i++) {
if (cc[i] == c) {
return i;
}
}
return -1;
}
}
class UBBNode {
static final String TEXT = "<text>";
String tag = null;
String attr = null;
String img = null;
UBBNode parent = null;
List children = null;
boolean closed = false;
boolean isEmpty = false;
UBBNode(UBBNode parent, String tag, String attr, String img, boolean isEmpty) {
this.parent = parent;
this.tag = tag.toLowerCase();
this.attr = attr;
this.img = img;
this.isEmpty = isEmpty;
this.closed = isEmpty;
this.children = isEmpty ? null : new ArrayList();
}
UBBNode(UBBNode parent, String text) {
this.parent = parent;
this.tag = TEXT;
this.attr = text;
this.img = text;
this.closed = true;
this.isEmpty = true;
}
final void addChild(UBBNode child) {
children.add(child);
}
public final String toString() {
return "[tag=\""+tag+"\",attr=\""+attr+"\",closed="+closed
+",children="+(children != null ? ""+children.size() : "null")+"]";
}
final String toString(int i) {
StringBuffer buf = new StringBuffer();
for (int j = i; --j >= 0;) {
buf.append(' ');
}
buf.append(toString() + "\n");
if (children != null && children.size() > 0) {
for (int j = 0, n = children.size(); j < n; j++) {
buf.append(((UBBNode) children.get(j)).toString(i + 2));
}
}
return buf.toString();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -