예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }