/// <summary>数値(2進数)を取得する。</summary>
        /// <param name="iter">イテレータ。</param>
        /// <returns>数値。</returns>
        private static ITomlValue Get2NumberValue(TomlInnerBuffer.TomlIter iter)
        {
            ulong v  = 0;
            bool  ud = false;
            UTF8  c;
            int   point = iter.Pointer;

            // 数値を取得する
            while ((c = iter.GetChar(0)).ch1 != 0)
            {
                // 1. '_'の連続の判定
                // 2. 数値の計算をする
                //    2-1. 数値の有効範囲を超えるならばエラー
                if (c.ch1 == '_')
                {
                    if (ud)                                 // 1
                    {
                        throw new TomlAnalisysException(Resources.UNDERBAR_CONTINUE_ERR, iter);
                    }
                    ud = true;
                }
                else if (c.ch1 == '0' || c.ch1 == '1')
                {
                    if (v <= ulong.MaxValue / 2)            // 2
                    {
                        v = v * 2 + (ulong)(c.ch1 - '0');
                    }
                    else                                    // 2-1
                    {
                        throw new TomlAnalisysException(Resources.INTEGER_VALUE_RANGE_ERR, iter);
                    }
                    ud = false;
                }
                else
                {
                    break;
                }
                iter.Skip(1);
            }

            // 一文字の数値もなければ None値を返す
            if (iter.Pointer == point)
            {
                return(TomlValue.Empty);
            }

            if (v <= ulong.MaxValue)
            {
                return(TomlValue.Create(v));
            }
            else
            {
                throw new TomlAnalisysException(Resources.INTEGER_VALUE_RANGE_ERR, iter);
            }
        }
Esempio n. 2
0
        /// <summary>配列内の値の型が全て一致するか判定する。</summary>
        /// <param name="array">判定する配列参照。</param>
        /// <param name="iter">イテレータ。</param>
        /// <returns>配列情報。</returns>
        private ITomlValue CheckArrayValueType(List <ITomlValue> array,
                                               TomlInnerBuffer.TomlIter iter)
        {
            TomlValueType type = TomlValueType.TomlNoneValue;

            // 全ての要素の型が一致することを確認
            if (array.Count > 0)
            {
                type = array[0].ValueType;

                for (int i = 1; i < array.Count; ++i)
                {
                    if (type != array[i].ValueType)
                    {
                        throw new TomlAnalisysException(Resources.ARRAY_VALUE_DIFFERENT_ERR, iter);
                    }
                }
            }

            // 配列を作成して返す
            switch (type)
            {
            case TomlValueType.TomlBooleanValue:
                var bools = array.Select(x => (bool)x.Raw).ToArray();
                return(TomlValue.Create(bools));

            case TomlValueType.TomlDateValue:
                var dates = array.Select(x => (TomlDate)x.Raw).ToArray();
                return(TomlValue.Create(dates));

            case TomlValueType.TomlFloatValue:
                var floats = array.Select(x => (double)x.Raw).ToArray();
                return(TomlValue.Create(floats));

            case TomlValueType.TomlIntegerValue:
                var longs = array.Select(x => (long)x.Raw).ToArray();
                return(TomlValue.Create(longs));

            case TomlValueType.TomlStringValue:
                var strings = array.Select(x => (string)x.Raw).ToArray();
                return(TomlValue.Create(strings));

            default:
                return(TomlValue.Create(array.ToArray()));
            }
        }
        //-----------------------------------------------------------------------------
        // 数値/日付解析
        //-----------------------------------------------------------------------------
        /// <summary>数値(日付/整数/実数)を取得する。</summary>
        /// <param name="iter">イテレータ。</param>
        /// <returns>値。</returns>
        internal static ITomlValue GetNumberOrDateValue(this TomlInnerBuffer.TomlIter iter)
        {
            int year, hour;

            if (ConvertPartitionNumber(iter, 0, 4, out year) &&
                iter.GetChar(4).ch1 == '-')
            {
                // 日付(年月日)を取得する
                return(TomlValue.Create(ConvertDateFormat(iter, year)));
            }
            else if (ConvertPartitionNumber(iter, 0, 2, out hour) &&
                     iter.GetChar(2).ch1 == ':')
            {
                // 日付(時分秒)を取得する
                return(TomlValue.Create(ConvertTimeFormat(iter, hour)));
            }
            else
            {
                // 数値(整数/実数)を取得する
                return(iter.GetNumberValue(false));
            }
        }
        //---------------------------------------------------------------------
        // 定数リテラル解析
        //---------------------------------------------------------------------
        /// <summary>数値(定数)を取得する。</summary>
        /// <param name="iter">イテレータ。</param>
        /// <param name="value">値(戻り値)</param>
        /// <returns>値が取得できたならば真。</returns>
        internal static bool AnalisysKeyword(this TomlInnerBuffer.TomlIter iter, out ITomlValue value)
        {
            // 真偽値(偽)を返す
            if (iter.RemnantLength >= 5)
            {
                if (iter.GetChar(4).ch1 == 'e' &&
                    iter.GetChar(3).ch1 == 's' &&
                    iter.GetChar(2).ch1 == 'l' &&
                    iter.GetChar(1).ch1 == 'a' &&
                    iter.GetChar(0).ch1 == 'f')
                {
                    value = TomlValue.False;
                    iter.Skip(5);
                    return(true);
                }
            }

            if (iter.RemnantLength >= 4)
            {
                // 真偽値(真)を返す
                if (iter.GetChar(3).ch1 == 'e' &&
                    iter.GetChar(2).ch1 == 'u' &&
                    iter.GetChar(1).ch1 == 'r' &&
                    iter.GetChar(0).ch1 == 't')
                {
                    value = TomlValue.True;
                    iter.Skip(4);
                    return(true);
                }

                // 正の無限値を返す
                if (iter.GetChar(3).ch1 == 'f' &&
                    iter.GetChar(2).ch1 == 'n' &&
                    iter.GetChar(1).ch1 == 'i' &&
                    iter.GetChar(0).ch1 == '+')
                {
                    value = TomlValue.Create(double.PositiveInfinity);
                    iter.Skip(4);
                    return(true);
                }

                // 負の無限値を返す
                if (iter.GetChar(3).ch1 == 'f' &&
                    iter.GetChar(2).ch1 == 'n' &&
                    iter.GetChar(1).ch1 == 'i' &&
                    iter.GetChar(0).ch1 == '-')
                {
                    value = TomlValue.Create(double.NegativeInfinity);
                    iter.Skip(4);
                    return(true);
                }

                // 正の非数値を返す
                if (iter.GetChar(3).ch1 == 'n' &&
                    iter.GetChar(2).ch1 == 'a' &&
                    iter.GetChar(1).ch1 == 'n' &&
                    iter.GetChar(0).ch1 == '+')
                {
                    value = TomlValue.Create(double.NaN);
                    iter.Skip(4);
                    return(true);
                }

                // 負の非数値を返す
                if (iter.GetChar(3).ch1 == 'n' &&
                    iter.GetChar(2).ch1 == 'a' &&
                    iter.GetChar(1).ch1 == 'n' &&
                    iter.GetChar(0).ch1 == '-')
                {
                    value = TomlValue.Create(-double.NaN);
                    iter.Skip(4);
                    return(true);
                }
            }

            if (iter.RemnantLength >= 3)
            {
                // 無限値を返す
                if (iter.GetChar(2).ch1 == 'f' &&
                    iter.GetChar(1).ch1 == 'n' &&
                    iter.GetChar(0).ch1 == 'i')
                {
                    value = TomlValue.Create(double.PositiveInfinity);
                    iter.Skip(3);
                    return(true);
                }

                // 非数値を返す
                if (iter.GetChar(2).ch1 == 'n' &&
                    iter.GetChar(1).ch1 == 'a' &&
                    iter.GetChar(0).ch1 == 'n')
                {
                    value = TomlValue.Create(double.NaN);
                    iter.Skip(3);
                    return(true);
                }
            }

            value = null;
            return(false);
        }
        /// <summary>数値(整数/実数)を取得する。</summary>
        /// <param name="iter">イテレータ。</param>
        /// <param name="numberSign">符号。</param>
        /// <returns>数値。</returns>
        private static ITomlValue Get10NumberValue(TomlInnerBuffer.TomlIter iter,
                                                   bool numberSign)
        {
            ulong v  = 0;
            bool  ud = false;
            UTF8  c;
            int   point = iter.Pointer;
            int   digit = -1;
            int   expo = -1;
            int   exp_v = -1;
            bool  ld_zero = false, lst_zero = false;

            // 仮数部を取得する
            while ((c = iter.GetChar(0)).ch1 != 0)
            {
                // 1. '_'の連続の判定
                // 2. 数値の計算をする
                //    2-1. 数値の有効範囲を超えるならばエラー
                // 3. 小数点位置を取得する
                // 4. 指数部(e)を取得する
                if (c.ch1 == '_')
                {
                    if (ud)                             // 1
                    {
                        throw new TomlAnalisysException(Resources.UNDERBAR_CONTINUE_ERR, iter);
                    }
                    ud = true;
                }
                else if (c.ch1 >= '0' && c.ch1 <= '9')
                {
                    if (v < ulong.MaxValue / 10)        // 2
                    {
                        v = v * 10 + (ulong)(c.ch1 - '0');
                        if (digit >= 0)
                        {
                            digit++;
                            lst_zero = true;
                        }
                        else
                        {
                            ld_zero = true;
                        }
                    }
                    else                                // 2-1
                    {
                        throw new TomlAnalisysException(Resources.INTEGER_VALUE_RANGE_ERR, iter);
                    }
                    ud = false;
                }
                else if (c.ch1 == '.')                  // 3
                {
                    if (ld_zero && digit < 0)
                    {
                        digit = 0;
                    }
                    else if (ld_zero)
                    {
                        throw new TomlAnalisysException(Resources.MULTI_DECIMAL_ERR, iter);
                    }
                    else
                    {
                        throw new TomlAnalisysException(Resources.NO_LEADING_ZERO_ERR, iter);
                    }
                }
                else if (c.ch1 == 'e' || c.ch1 == 'E')
                {
                    expo = 0;                           // 4
                    break;
                }
                else
                {
                    break;
                }
                iter.Skip(1);
            }

            // 一文字の数値もなければ None値を返す
            if (iter.Pointer == point)
            {
                return(TomlValue.Empty);
            }

            // 仮数部を取得する
            CalcExponentConvert(iter, digit, expo, out exp_v);

            if (digit < 0 && expo < 0)
            {
                // 整数値を取得する
                //
                // 1. 負の整数変換
                // 2. 正の整数変換
                if (numberSign)
                {
                    if (v <= (ulong)long.MaxValue)          // 1
                    {
                        return(TomlValue.Create(-(long)v));
                    }
                    else if (v == (ulong)long.MaxValue + 1)
                    {
                        return(TomlValue.Create(long.MinValue));
                    }
                    else
                    {
                        throw new TomlAnalisysException(Resources.DOUBLE_VALUE_RANGE_ERR, iter);
                    }
                }
                else
                {
                    if (v <= long.MaxValue)                 //2
                    {
                        return(TomlValue.Create((long)v));
                    }
                    else
                    {
                        throw new TomlAnalisysException(Resources.DOUBLE_VALUE_RANGE_ERR, iter);
                    }
                }
            }
            else
            {
                if (digit >= 0 && !lst_zero)
                {
                    throw new TomlAnalisysException(Resources.NO_LAST_ZERO_ERR, iter);
                }

                // 実数値を取得する
                //
                // 1. 負の指数なら除算
                // 2. 正の指数なら積算
                // 3. 0の指数なら使用しない
                // 4. 値を保持
                double dv = 0;
                if (exp_v < 0)
                {
                    double abs_e = 1;                   // 1
                    for (int i = 0; i < Math.Abs(exp_v); ++i)
                    {
                        abs_e *= 10;
                    }
                    dv = (double)v / abs_e;
                }
                else if (exp_v > 0)
                {
                    double abs_e = 1;                   // 2
                    for (int i = 0; i < Math.Abs(exp_v); ++i)
                    {
                        abs_e *= 10;
                    }
                    dv = (double)v * abs_e;
                }
                else
                {
                    dv = (double)v;                     // 3
                }
                if (dv <= double.MaxValue)              // 4
                {
                    return(TomlValue.Create(numberSign ? (double)-dv : (double)dv));
                }
                else
                {
                    throw new TomlAnalisysException(Resources.DOUBLE_VALUE_RANGE_ERR, iter);
                }
            }
        }
Esempio n. 6
0
        /// <summary>テーブル配列を作成する。</summary>
        /// <param name="iter">イテレータ。</param>
        /// <param name="table">カレントテーブル。</param>
        private void AnalisysTableArray(TomlInnerBuffer.TomlIter iter, TomlTable table)
        {
            // '.' で区切られたテーブル名を事前に収集する
            var keyPtr = iter.GetKeys();

            // テーブル配列が閉じられているか確認
            if (!iter.CloseTableArray())
            {
                throw new TomlAnalisysException(Resources.TABLE_ARRAY_SYNTAX_ERR, iter);
            }

            // 最下層のテーブル以外のテーブル参照を収集する
            //
            // 1. テーブル参照を取得
            // 2. エラーが有れば終了
            // 3. 既に作成済みならばカレントを変更
            // 4. 作成されていなければテーブルを作成し、カレントに設定
            TomlTable curTable = table;
            TomlTable newTable = null;
            string    keystr   = "";

            for (int i = 0; i < keyPtr.Count - 1; ++i)
            {
                keystr = keyPtr[i];

                switch (curTable.SearchPathTable(keystr, out newTable))     // 1
                {
                case 0:                                                     // 2
                    throw new TomlAnalisysException(Resources.TABLE_REDEFINITION_ERR, iter);

                case 1:
                    curTable = newTable;                                    // 3
                    break;

                default:
                    newTable = new TomlTable();                             // 4
                    curTable.AddKeyAndValue(keystr, newTable);
                    curTable = newTable;
                    break;
                }
            }

            // 最下層のテーブルは新規作成となる
            //
            // 1. 登録する名前(キー文字列)を取得
            // 2. 親のテーブルに最下層のテーブル名が登録されている
            //    2-1. 登録されている名前のデータを取得する
            //    2-2. テーブル配列が登録されているならば、新規テーブルを作成し、カレントテーブルとする
            //    2-3. テーブル配列でないならばエラーとする
            // 3. 親のテーブルに最下層のテーブル名が登録されていない
            //    3-1. テーブル配列を作成し、テーブルを追加、追加されたテーブルが次のカレントテーブルになる
            keystr = keyPtr[keyPtr.Count - 1];                              // 1

            if (curTable.Contains(keystr))                                  // 2-1
            {
                var val = curTable.Member(keystr);
                if (val.ValueType == TomlValueType.TomlTableArrayValue)     // 2-2
                {
                    newTable = new TomlTable();
                    ((Array <TomlTable>)val).Add(newTable);
                }
                else                                                        // 2-3
                {
                    throw new TomlAnalisysException(Resources.DEFINED_KEY_ERR, iter);
                }
            }
            else
            {
                newTable = new TomlTable();                                 // 3-1
                var newArr = TomlValue.Create(new TomlTable[] { newTable });
                curTable.AddKeyAndValue(keystr, newArr);
            }

            // カレントのテーブルを作成したテーブルに変更
            this.current = newTable;
            iter.SkipSpace();
        }
Esempio n. 7
0
        /// <summary>数値(整数/実数/日付)を取得する。</summary>
        /// <param name="iter">イテレータ。</param>
        /// <returns>値情報。</returns>
        private ITomlValue ConvertValue(TomlInnerBuffer.TomlIter iter)
        {
            ITomlValue value = null;

            // 値リテラルを解析する
            if (iter.AnalisysKeyword(out value))
            {
                return(value);
            }

            // 複数ライン文字列を返す
            if (iter.RemnantLength >= 3)
            {
                // 複数ライン文字列を返す
                if (iter.GetChar(2).ch1 == '"' &&
                    iter.GetChar(1).ch1 == '"' &&
                    iter.GetChar(0).ch1 == '"')
                {
                    iter.Skip(3);
                    return(TomlValue.Create(iter.GetMultiStringValue()));
                }

                // 複数ライン文字列(リテラル)を返す
                if (iter.GetChar(2).ch1 == '\'' &&
                    iter.GetChar(1).ch1 == '\'' &&
                    iter.GetChar(0).ch1 == '\'')
                {
                    iter.Skip(3);
                    return(TomlValue.Create(iter.GetMultiLiteralStringValue()));
                }
            }

            // 数値/日付/文字列
            if (iter.RemnantLength > 0)
            {
                switch (iter.GetChar(0).ch1)
                {
                case (byte)'"':
                    // 文字列を取得する
                    iter.Skip(1);
                    return(TomlValue.Create(iter.GetStringValue()));

                case (byte)'\'':
                    // リテラル文字列を取得する
                    iter.Skip(1);
                    return(TomlValue.Create(iter.GetLiteralStringValue()));

                case (byte)'#':
                    // コメントを取得する
                    iter.Skip(1);
                    return(null);

                case (byte)'+':
                    // 数値を取得する
                    iter.Skip(1);
                    return(iter.GetNumberValue(false));

                case (byte)'-':
                    // 数値を取得する
                    iter.Skip(1);
                    return(iter.GetNumberValue(true));

                default:
                    // 日付/数値を取得する
                    return(iter.GetNumberOrDateValue());
                }
            }
            else
            {
                throw new TomlAnalisysException(Resources.NOT_DEFINED_VALUE_ERR, iter);
            }
        }