package com.owent.xresloader.data.dst; import com.owent.xresloader.ProgramOptions; import com.owent.xresloader.data.err.ConvException; import com.owent.xresloader.scheme.SchemeConf; import org.json.JSONObject; import java.nio.charset.Charset; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by owentou on 2014/10/10. */ public class DataDstLua extends DataDstJava { private String endl = "\n"; private String ident = " "; @Override public boolean init() { if (ProgramOptions.getInstance().prettyIndent <= 0) { endl = " "; ident = ""; } else { endl = getSystemEndl(); ident = ""; for (int i = 0; i < ProgramOptions.getInstance().prettyIndent; ++ i) { ident += " "; } } return true; } /** * @return 协议处理器名字 */ public String name() { return "lua"; } @Override public final byte[] build(DataDstImpl compiler) throws ConvException { DataDstJava.DataDstObject data_obj = build_data(compiler); StringBuffer sb = new StringBuffer(); sb.append("-- this file is generated by xresloader, please don't edit it.").append(getSystemEndl()).append(endl); sb.append("return {").append(endl); // header sb.append(ident).append("[1] = "); writeData(sb, data_obj.header, 1); sb.append(",").append(endl); // body for(Map.Entry<String, List<Object> > item: data_obj.body.entrySet()) { writeIdent(sb, 1); sb.append(item.getKey()).append(" = "); writeData(sb, item.getValue(), 1); sb.append(",").append(endl); } sb.append("}"); // 带编码的输出 String encoding = SchemeConf.getInstance().getKey().getEncoding(); if (null == encoding || encoding.isEmpty()) return sb.toString().getBytes(); return sb.toString().getBytes(Charset.forName(encoding)); } @Override public final DataDstWriterNode compile() { ProgramOptions.getLoger().error("lua can not be protocol description."); return null; } private void writeIdent(StringBuffer sb, int ident_num) { for(; ident_num > 0; -- ident_num) { sb.append(ident); } } private void writeData(StringBuffer sb, Object data, int ident_num) { // null if (null == data) { sb.append("nil"); return; } // 数字 // 枚举值已被转为Java Long,会在这里执行 if (data instanceof Number) { sb.append(data.toString()); return; } // 布尔 if (data instanceof Boolean) { sb.append(((Boolean) data)? "true": "false"); return; } // 字符串&二进制 if (data instanceof String) { // 利用json的字符串格式,和lua一样的没必要再引入一个库 sb.append(JSONObject.quote((String)data)); return; } // 列表 if (data instanceof List) { List<Object> ls = (List<Object>)data; sb.append("{").append(endl); for(Object obj: ls) { writeIdent(sb, ident_num + 1); writeData(sb, obj, ident_num + 1); sb.append(",").append(endl); } writeIdent(sb, ident_num); sb.append("}"); return; } // Hashmap if (data instanceof Map) { Map<String, Object> mp = (Map<String, Object>)data; sb.append("{").append(endl); for(Map.Entry<String, Object> item: mp.entrySet()) { writeIdent(sb, ident_num + 1); sb.append(item.getKey()).append(" = "); writeData(sb, item.getValue(), ident_num + 1); sb.append(",").append(endl); } writeIdent(sb, ident_num); sb.append("}"); return; } ProgramOptions.getLoger().error("rewrite %s as nil, should not called here.", data.toString()); sb.append("nil"); } /** * 转储常量数据 * @return 常量数据,不支持的时候返回空 */ public final byte[] dumpConst(HashMap<String, Object> data) { init(); StringBuffer sb = new StringBuffer(); sb.append("-- this file is generated by xresloader, please don't edit it.").append(getSystemEndl()).append(endl); sb.append("local const_res = "); writeData(sb, data, 0); sb.append(endl).append(endl); // 写入全局,需要防止覆盖问题 if (ProgramOptions.getInstance().luaGlobal) { sb.append("local function extend(dst, src)").append(endl); sb.append(ident).append("for k, v in pairs(src) do").append(endl); sb.append(ident).append(ident).append("if not dst[k] or 'table' ~= type(v) then").append(endl); sb.append(ident).append(ident).append(ident).append("dst[k] = src[k]").append(endl); sb.append(ident).append(ident).append("else").append(endl); sb.append(ident).append(ident).append(ident).append("if 'table' ~= type(dst[k]) then").append(endl); sb.append(ident).append(ident).append(ident).append(ident).append("dst[k] = {}").append(endl); sb.append(ident).append(ident).append(ident).append("end").append(endl); sb.append(ident).append(ident).append(ident).append("extend(dst[k], src[k])").append(endl); sb.append(ident).append(ident).append("end").append(endl); sb.append(ident).append("end").append(endl); sb.append("end").append(endl); sb.append("extend(_G, const_res)").append(endl).append(endl); } sb.append("return const_res").append(endl); // 带编码的输出 String encoding = SchemeConf.getInstance().getKey().getEncoding(); if (null == encoding || encoding.isEmpty()) return sb.toString().getBytes(); return sb.toString().getBytes(Charset.forName(encoding)); } }