private bool TryGetTypeArray(eParaType t, int count, out Array arr) { switch (t) { case eParaType.Int: arr = new int[count]; return(true); case eParaType.UInt: arr = new uint[count]; return(true); case eParaType.Long: arr = new long[count]; return(true); case eParaType.ULong: arr = new ulong[count]; return(true); case eParaType.Float: arr = new float[count]; return(true); case eParaType.Double: arr = new double[count]; return(true); case eParaType.Bool: arr = new bool[count]; return(true); case eParaType.String: arr = new string[count]; return(true); } arr = null; return(false); }
private bool TryParseValue(string p, eParaType t, out object val) { double d; switch (t) { case eParaType.Int: if (Calculate(p, out d) && !double.IsNaN(d)) { val = (int)d; return(true); } break; case eParaType.UInt: if (Calculate(p, out d) && !double.IsNaN(d)) { val = (uint)d; return(true); } break; case eParaType.Long: if (Calculate(p, out d) && !double.IsNaN(d)) { val = (long)d; return(true); } break; case eParaType.ULong: if (Calculate(p, out d) && !double.IsNaN(d)) { val = (ulong)d; return(true); } break; case eParaType.Float: if (Calculate(p, out d) && !double.IsNaN(d)) { val = (float)d; return(true); } break; case eParaType.Double: if (Calculate(p, out d) && !double.IsNaN(d)) { val = d; return(true); } break; case eParaType.Bool: bool boolValue; if (bool.TryParse(p, out boolValue)) { val = boolValue; return(true); } break; case eParaType.String: val = ""; try { val = GetStringInternal(p); } catch (Exception e) { if (onWarning != null) { onWarning(e.Message); } return(false); } return(true); } val = null; return(false); }
private string RegFunc(object target, string funcName, MethodInfo method) { if (method.IsGenericMethod || method.ContainsGenericParameters) { return("Generic method is not supported !"); } if (method.ReturnType != s_type_string) { return(string.Format("Function '{0}' should return a string !", method.Name)); } ParameterInfo[] paras = method.GetParameters(); FunctionData funcData = new FunctionData(); funcData.target = target; funcData.method = method; funcData.paraTypes = new List <eParaType>(); funcData.hasArrayParams = false; //Debug.Log("method name : " + method.Name); for (int j = 0, jmax = paras.Length - 1; j <= jmax; j++) { ParameterInfo para = paras[j]; Type tParam = para.ParameterType; //Debug.Log("method para type : " + tParam); eParaType eType = eParaType.Unsupported; if (tParam.IsArray) { if (j == jmax) { eType = GetParaType(tParam.GetElementType()); funcData.hasArrayParams = true; //Debug.Log(GetParaType(tParam.GetElementType()) + " array"); } else { return("Array can only be the last param"); } } else { eType = GetParaType(tParam); //Debug.LogWarning(GetParaType(tParam)); } if (eType == eParaType.Unsupported) { return(string.Format("Type '{0}' not supportted !", tParam)); } funcData.paraTypes.Add(eType); } mAliases.Clear(); mCachedErrors.Remove(0, mCachedErrors.Length); if (string.IsNullOrEmpty(funcName)) { mAliases.Add(method.Name); StringEnricherAliasAttribute[] aliases = method.GetCustomAttributes(typeof(StringEnricherAliasAttribute), false) as StringEnricherAliasAttribute[]; for (int i = 0, imax = aliases == null ? 0 : aliases.Length; i < imax; i++) { StringEnricherAliasAttribute alias = aliases[i]; for (int j = 0, jmax = alias.alias.Length; j < jmax; j++) { string a = alias.alias[j]; if (!mAliases.Contains(a)) { mAliases.Add(a); } } } } else { mAliases.Add(funcName); } for (int i = 0, imax = mAliases.Count; i < imax; i++) { string alias = mAliases[i]; string key = string.Format("{0}:{1}{2}", alias, funcData.paraTypes.Count, funcData.hasArrayParams ? "+" : ""); if (mFunctions.ContainsKey(key)) { mCachedErrors.AppendLine(string.Format("Method ({0}) with same name, param amount but different para type is not supportted !", alias)); continue; } mFunctions.Add(key, funcData); } mAliases.Clear(); string ret = mCachedErrors.Length > 0 ? mCachedErrors.ToString() : null; mCachedErrors.Remove(0, mCachedErrors.Length); return(ret); }
private string GetStringInternal(string str) { if (string.IsNullOrEmpty(str)) { return(null); } int index = 0; int length = str.Length; string funcName = GetSegment(str, ref index); char chr = GetNextChar(str, index - 1); if (string.IsNullOrEmpty(funcName)) { throw new Exception(string.Format("Unexpected char '{0}', at '{1}' !", chr, index)); } if (chr != '(') { if (funcName[0] == '$') { return(string.Concat(GetVariableString(funcName.Substring(1, funcName.Length - 1)), str.Substring(index, length - index))); } return(str); } index++; mCachedParams.Clear(); int pStart = index; int pLength = 0; bool inQuote = false; bool isTrans = false; int bracketCount = 0; bool done = false; while (index < length) { isTrans = isTrans ? false : chr == '\\'; chr = str[index++]; if (chr == ',') { if (!inQuote && bracketCount == 0) { string p = str.Substring(pStart, pLength); if (string.IsNullOrEmpty(p.Trim())) { throw new Exception(string.Format("Unexpected char '{0}', at {1} !", chr, (index - 1))); } mCachedParams.Add(p); pStart = index; pLength = -1; } } else if (chr == ')') { if (!inQuote) { bracketCount--; if (bracketCount < 0) { string p = str.Substring(pStart, pLength); if (string.IsNullOrEmpty(p.Trim())) { if (mCachedParams.Count > 0) { throw new Exception(string.Format("Unexpected char '{0}', at {1} !", chr, (index - 1))); } } else { mCachedParams.Add(p); } done = true; break; } } } else if (chr == '(') { if (!inQuote) { bracketCount++; } } else if (chr == '\"') { if (!isTrans) { inQuote = !inQuote; } } pLength++; } if (!done) { throw new Exception("Statement not finished !"); } //Debug.LogWarning(string.Format("{0}({1})", funcName, string.Join(", ", mCachedParams.ToArray()))); int count = mCachedParams.Count; int min = count > 1 ? 1 : count; bool firstCheck = true; FunctionData funcData = null; while (count >= min) { string key = null; if (firstCheck) { key = string.Format("{0}:{1}", funcName, count); firstCheck = false; count++; } else if (count > 0) { key = string.Format("{0}:{1}+", funcName, count); count--; } else { break; } //Debug.LogWarning("key when dispatch : " + key); if (mFunctions.TryGetValue(key, out funcData)) { break; } } if (funcData == null) { throw new Exception(string.Format("Cannot find matched command '{0}' !" + str)); } int normalParaCount = funcData.paraTypes.Count; if (funcData.hasArrayParams) { normalParaCount--; } string errorParam = null; eParaType errorType = eParaType.Unsupported; int parasCount = funcData.paraTypes.Count; object[] paras = new object[parasCount]; int parasIndex = 0; for (int i = 0; i < normalParaCount; i++) { string para = mCachedParams[i]; object val; if (TryParseValue(para, funcData.paraTypes[i], out val)) { paras[parasIndex] = val; parasIndex++; } else { errorParam = para; errorType = funcData.paraTypes[i]; break; } } if (errorParam != null) { throw new Exception(string.Format("Fail to parse '{0}' into {1} !", errorParam, errorType)); } if (funcData.hasArrayParams) { eParaType arrayItemType = funcData.paraTypes[normalParaCount]; int arrayParasCount = mCachedParams.Count; Array arrayParas; if (!TryGetTypeArray(arrayItemType, arrayParasCount - normalParaCount, out arrayParas)) { throw new Exception("Fail to get array parameters array"); } //Debug.Log("arrayParasCount " + arrayParasCount + " " + arrayParas.Length); for (int i = normalParaCount; i < arrayParasCount; i++) { string para = mCachedParams[i]; object val; if (TryParseValue(para, funcData.paraTypes[normalParaCount], out val)) { arrayParas.SetValue(val, i - normalParaCount); } else { errorParam = para; errorType = funcData.paraTypes[normalParaCount]; } } paras[parasIndex] = arrayParas; parasIndex++; } if (errorParam != null) { throw new Exception(string.Format("fail to parse '{0}' into {1}", errorParam, errorType)); } mCachedParams.Clear(); //Debug.Log("ready to invoke command : " + funcData.method.Name); return((string)funcData.method.Invoke(funcData.target, paras)); }
private bool TryParseValue(string p, eParaType t, out object val) { switch (t) { case eParaType.Int: int intValue; if (int.TryParse(p, out intValue)) { val = intValue; return(true); } break; case eParaType.UInt: uint uintValue; if (uint.TryParse(p, out uintValue)) { val = uintValue; return(true); } break; case eParaType.Long: long longValue; if (long.TryParse(p, out longValue)) { val = longValue; return(true); } break; case eParaType.ULong: ulong ulongValue; if (ulong.TryParse(p, out ulongValue)) { val = ulongValue; return(true); } break; case eParaType.Float: float floatValue; if (float.TryParse(p, out floatValue)) { val = floatValue; return(true); } break; case eParaType.Double: double doubleValue; if (double.TryParse(p, out doubleValue)) { val = doubleValue; return(true); } break; case eParaType.Bool: bool boolValue; if (bool.TryParse(p, out boolValue)) { val = boolValue; return(true); } break; case eParaType.String: val = p; return(true); } val = null; return(false); }
private void AddCommand(string methodName, object obj, MethodInfo method, IList <string> errors) { if (method.IsGenericMethod || method.ContainsGenericParameters) { errors.Add(string.Format("Generic method or method with generic parameters is not supported ! (At '{0}')", method.Name)); return; } if (!method.IsStatic && obj == null) { errors.Add(string.Format("Instance is required when method is non static ! (At '{0}')", method.Name)); return; } mCachedCmdNames.Clear(); bool aliasSet = false; if (!string.IsNullOrEmpty(methodName)) { aliasSet = true; mCachedCmdNames.Add(methodName); } CommandAliasAttribute[] aliases = method.GetCustomAttributes(typeof(CommandAliasAttribute), false) as CommandAliasAttribute[]; if (aliases != null && aliases.Length > 0) { for (int i = 0, imax = aliases.Length; i < imax; i++) { CommandAliasAttribute alias = aliases[i]; for (int j = 0, jmax = alias.alias.Length; j < jmax; j++) { string a = alias.alias[j]; if (string.IsNullOrEmpty(a) || a == methodName) { continue; } mCachedCmdNames.Add(a); aliasSet = true; } } } if (!aliasSet) { mCachedCmdNames.Add(method.Name); } ParameterInfo[] paras = method.GetParameters(); CommandData cmd = new CommandData(); int firstParaIndex = 0; if (paras.Length > 0) { ParameterInfo param = paras[0]; if (param.ParameterType.Equals(s_type_list_cmdopt) || param.ParameterType.Equals(s_type_ilist_cmdopt)) { firstParaIndex = 1; cmd.hasOptions = true; } } cmd.obj = obj; cmd.method = method; cmd.paraTypes = new List <eParaType>(); cmd.hasArrayParams = false; for (int j = firstParaIndex, jmax = paras.Length - 1; j <= jmax; j++) { ParameterInfo para = paras[j]; Type tParam = para.ParameterType; eParaType eType = eParaType.Unsupported; if (tParam.IsArray) { if (j != jmax) { errors.Add(string.Format("Array can only be the last param ! (At '{0}')", method.Name)); return; } eType = GetParaType(tParam.GetElementType()); cmd.hasArrayParams = true; //Debug.Log(GetParaType(tParam.GetElementType()) + " array"); } else { eType = GetParaType(tParam); //Debug.LogWarning(GetParaType(tParam)); } if (eType == eParaType.Unsupported) { errors.Add(string.Format("Type '{0}' not supported ! (At '{0}')", tParam, method.Name)); return; } cmd.paraTypes.Add(eType); } int ret = 0; for (int i = 0, imax = mCachedCmdNames.Count; i < imax; i++) { string cmdName = mCachedCmdNames[i]; string key = string.Format("{0}:{1}{2}", cmdName, cmd.paraTypes.Count, cmd.hasArrayParams ? "+" : ""); if (mCmds.ContainsKey(key)) { errors.Add(string.Format("Method with same name, param amount but different para type is not supported ! (At '{0}')", method.Name)); ret++; continue; } mCmds.Add(key, cmd); CommandManualAttribute manual = Attribute.GetCustomAttribute(method, typeof(CommandManualAttribute)) as CommandManualAttribute; if (manual != null) { List <string> ms; if (mManuals.TryGetValue(cmdName, out ms)) { ms.Add(manual.manual); } else { ms = new List <string>(); ms.Add(manual.manual); mManuals.Add(cmdName, ms); } } } }
/// <summary> /// The method for executing a command. /// </summary> /// <param name="cmd">A command string that contains command name and parameters</param> public void Execute(string cmd) { if (string.IsNullOrEmpty(cmd)) { return; } int index = 0; int length = cmd.Length; int start = 0; bool inQuote = false; bool isLastQuote = false; bool isTrans = false; bool expectEmpty = false; string cmdName = null; int contentType = 0; mCachedParams.Clear(); mCachedCmdOpts.Clear(); string error = null; while (index < length) { char c = cmd[index]; bool isLast = index == length - 1; bool trans = false; bool isEmpty = c == ' ' || c == '\t'; bool forceBreak = false; int nextContentType = -1; if (expectEmpty && !isEmpty) { error = "Empty char expected"; break; } expectEmpty = false; bool quote = false; if (c == '"') { if (!isTrans) { quote = true; inQuote = !inQuote; if (inQuote) { if (start != index) { error = "'\"' can only be the start of a content !"; break; } } else { expectEmpty = true; } } } else if (c == '\\') { trans = true; } else if (c == '-') { if (enableOptions && start == index) { if (mCachedParams.Count > 0 || contentType == 0) { error = "Options should be between command name and the first parameter !"; break; } nextContentType = 1; start = index + 1; } } else if (c == ':') { if (contentType == 1) { nextContentType = 2; forceBreak = true; } } if (isEmpty || isLast || forceBreak) { if (!inQuote) { if (index > start || isLast) { int startIndex = start; int strLength = index - start; if (isLastQuote || (isLast && quote)) { startIndex++; strLength -= 2; } string ss = cmd.Substring(startIndex, isLast ? strLength + 1 : strLength); if (contentType == 0) { cmdName = ss; //Debug.Log("cmd name : " + cmdName); contentType = 10; } else if (contentType == 1) { //Debug.Log("options : " + ss); for (int i = 0, imax = ss.Length; i < imax; i++) { CommandOption opt = new CommandOption(); opt.optionName = ss[i]; mCachedCmdOpts.Add(opt); } if (c == ':') { if (ss.Length != 1) { error = "Option parameter cannot follow multi options !"; break; } } else { nextContentType = 10; } } else if (contentType == 2) { //Debug.Log("option param : " + ss); int i = mCachedCmdOpts.Count - 1; CommandOption opt = mCachedCmdOpts[i]; opt.optionParam = ss; mCachedCmdOpts[i] = opt; nextContentType = 10; } else { mCachedParams.Add(ss.Replace("\\\"", "\"")); //Debug.Log("param : " + ss.Replace("\\\"", "\"")); } } start = index + 1; } } isLastQuote = quote; isTrans = trans; if (nextContentType >= 0) { contentType = nextContentType; } index++; } if (error != null) { throw new Exception(string.Format("{0} at {1}", error, index)); } //List<string> opts = new List<string>(); //foreach (CommandOption o in mCachedCmdOpts) { //opts.Add(string.Format("{0}:{1}", o.optionName, o.optionParam)); //} //Debug.Log(string.Format("cmd name : {0} opts : [{1}] params : [{2}]", cmdName, // string.Join(", ", opts.ToArray()), string.Join(", ", mCachedParams.ToArray()))); int count = mCachedParams.Count; int min = count > 1 ? 1 : count; bool firstCheck = true; CommandData cmdData = null; while (count >= min) { string key = null; if (firstCheck) { key = string.Format("{0}:{1}", cmdName, count); firstCheck = false; count++; } else if (count > 0) { key = string.Format("{0}:{1}+", cmdName, count); count--; } else { break; } if (mCmds.TryGetValue(key, out cmdData)) { break; } } if (cmdData == null) { throw new Exception(string.Format("Cannot find matched command '{0}' !", cmd)); } if (!cmdData.hasOptions && mCachedCmdOpts.Count > 0) { throw new Exception(string.Format("Command '{0}' does not require any options !", cmd)); } int normalParaCount = cmdData.paraTypes.Count; if (cmdData.hasArrayParams) { normalParaCount--; } string errorParam = null; eParaType errorType = eParaType.Unsupported; int parasCount = cmdData.paraTypes.Count; if (cmdData.hasOptions) { parasCount++; } object[] paras = new object[parasCount]; int parasIndex = 0; if (cmdData.hasOptions) { paras[parasIndex] = mCachedCmdOpts; parasIndex++; } for (int i = 0; i < normalParaCount; i++) { string para = mCachedParams[i]; object val; if (TryParseValue(para, cmdData.paraTypes[i], out val)) { paras[parasIndex] = val; parasIndex++; } else { errorParam = para; errorType = cmdData.paraTypes[i]; break; } } if (errorParam != null) { throw new Exception(string.Format("Fail to parse '{0}' into {1} !", errorParam, errorType)); } if (cmdData.hasArrayParams) { eParaType arrayItemType = cmdData.paraTypes[normalParaCount]; int arrayParasCount = mCachedParams.Count; Array arrayParas; if (!TryGetTypeArray(arrayItemType, arrayParasCount - normalParaCount, out arrayParas)) { throw new Exception("Fail to get array parameters array !"); } for (int i = normalParaCount; i < arrayParasCount; i++) { string para = mCachedParams[i]; object val; if (TryParseValue(para, cmdData.paraTypes[normalParaCount], out val)) { arrayParas.SetValue(val, i - normalParaCount); } else { errorParam = para; errorType = cmdData.paraTypes[normalParaCount]; } } paras[parasIndex] = arrayParas; parasIndex++; } if (errorParam != null) { throw new Exception(string.Format("Fail to parse '{0}' into {1}", errorParam, errorType)); } //Debug.Log("ready to invoke command : " + cmdData.method.Name); cmdData.method.Invoke(cmdData.obj, paras); }