コード例 #1
0
        private unsafe static bool TryParseFloatFormat_v2(Char16 *ptr_source,
                                                          int length,
                                                          out int sign,
                                                          out int i_start,
                                                          out int dot_pos,
                                                          out int exp_pos,
                                                          out int n_pow)
        {
            // check sign on front
            i_start = 0;
            if (ptr_source[0].IsSign(out sign))
            {
                i_start = 1;
            }

            // eat zeros on the head
            bool is_zero_head = false;

            for (int i = i_start; i < length; i++)
            {
                UInt16 c = ptr_source[i];
                if (c == UTF16CodeSet.code_0)
                {
                    is_zero_head = true;
                    i_start++;
                }
                else
                {
                    break;
                }
            }

            // initialize value
            dot_pos = -1;
            exp_pos = -1;
            n_pow   = 0;

            if (length > 2048)
            {
                return(false);
            }

            // check dot pos
            // check exp pos
            int  dummy;
            bool is_digit_found = false;

            for (int i = i_start; i < length; i++)
            {
                Char16 c = ptr_source[i];

                if (!is_digit_found && c.IsDigit(out dummy))
                {
                    is_digit_found = true;
                }
                else if (c.IsDot())
                {
                    if (dot_pos >= 0)
                    {
                        return(false);               // # of dots must be 0 or 1 in string.
                    }
                    dot_pos = i;
                }
                else if (c.IsExp())
                {
                    if (!is_digit_found &&
                        !is_zero_head)
                    {
                        return(false);                // must have digits before [E/e] mark.
                    }
                    if (exp_pos > 0)
                    {
                        return(false);                // # of [E/e] marks must be 0 or 1 in string.
                    }
                    exp_pos = i;
                }
            }

            // check exp sign
            int exp_start = exp_pos + 1;
            int exp_sign  = 1;

            if (exp_pos > 0)
            {
                if (ptr_source[exp_start].IsSign(out exp_sign))
                {
                    exp_start += 1;
                }
                if (exp_start == length)
                {
                    return(false);                      // no digits in exp
                }
            }
            else
            {
                exp_pos   = (short)length;
                exp_start = exp_pos;
            }

            // check mantissa region is digits only or not
            for (int i = i_start; i < exp_pos; i++)
            {
                Char16 c = ptr_source[i];
                if (!c.IsDigit(out dummy) && !c.IsDot())
                {
                    return(false);
                }
            }

            // check exp region and extract n_pow
            if (exp_start > 0)
            {
                for (int i = 0; i < math.min(length - exp_start, 64); i++) // up to 64 digits for pow
                {
                    Char16 c = ptr_source[i + exp_start];

                    if (!c.IsDigit(out int d))
                    {
                        return(false);                        // exp region must be digits only
                    }
                    n_pow = n_pow * 10 + (int)d;
                    if (n_pow > 350)
                    {
                        if (exp_sign > 0)
                        {
                            // overflow
                            return(false);
                        }
                        break;
                    }
                }
                n_pow *= exp_sign;
            }

            // parsing manntissa search [i_start, exp_pos] and use dot_pos to calc 10^m in mantissa.
            if (dot_pos < 0)
            {
                dot_pos = exp_pos;
            }

            return(true);
        }
コード例 #2
0
        private unsafe static bool TryParseFloatFormat(Char16 *ptr_source,
                                                       int length,
                                                       out int sign,
                                                       out int i_start,
                                                       out int dot_pos,
                                                       out int exp_pos,
                                                       out int n_pow)
        {
            i_start = 0;
            if (ptr_source[0].IsSign(out sign))
            {
                i_start = 1;
            }

            bool zero_head = false;

            // eat zeros on the head
            for (int i = i_start; i < length; i++)
            {
                UInt16 c = ptr_source[i];
                if (c == UTF16CodeSet.code_0)
                {
                    i_start++;
                    zero_head = true;
                }
                else
                {
                    break;
                }
            }

            dot_pos = -1;
            exp_pos = -1;

            n_pow = 0;
            int exp_sign = 1;

            int digit_count = 0;

            int dummy;
            int dummy_sign;

            int exp_start = -1;;

            // format check
            for (int i = i_start; i < length; i++)
            {
                Char16 c = ptr_source[i];
                //UnityEngine.Debug.Log($"parse format: i={i}, c={c}");
                if (c.IsDigit(out dummy))
                {
                    if (exp_pos == -1)
                    {
                        digit_count++;
                    }
                    // do nothing
                    //UnityEngine.Debug.Log("c is number");
                }
                else
                {
                    if (exp_start > 0 && i >= exp_start)
                    {
                        return(false);                                   // after [e/E] region must be digits.
                    }
                    if (c.IsDot())
                    {
                        if (dot_pos != -1 || dot_pos == i_start + 1)
                        {
                            return(false);
                        }
                        if (exp_pos > 0 && i >= exp_pos)
                        {
                            return(false);
                        }
                        dot_pos = i;
                        //UnityEngine.Debug.Log("c is dot");
                    }
                    else if (c.IsExp())
                    {
                        //UnityEngine.Debug.Log("c is EXP");

                        if (exp_pos != -1)
                        {
                            return(false);                                 // 2nd [e/E] found
                        }
                        if (digit_count == 0 && !zero_head)
                        {
                            return(false);                                 // no digits before [e/E]
                        }
                        if (length - i == 0)
                        {
                            return(false);                                 // no digits after [e/E]
                        }
                        if ((length - i == 1) &&
                            !ptr_source[i + 1].IsDigit(out dummy))
                        {
                            return(false);
                        }

                        exp_pos   = i;
                        exp_start = i + 1;

                        if (ptr_source[i + 1].IsSign(out exp_sign))
                        {
                            if (exp_start + 1 >= length)
                            {
                                return(false);                          // ended by [e/E][+/-]. no pow digits.
                            }
                            exp_start += 1;
                        }
                    }
                    else if (c.IsSign(out dummy_sign))
                    {
                        if (i != exp_pos + 1)
                        {
                            return(false);
                        }
                        exp_start = i + 1;
                    }
                    else
                    {
                        //UnityEngine.Debug.Log("failure to parse");
                        return(false);
                    }
                }
            }

            // decode exp part
            if (exp_start > 0)
            {
                for (int i = 0; i < math.min(length - exp_start, 32); i++) // up to 32 digits for pow
                {
                    n_pow = n_pow * 10 + ptr_source[i + exp_start].ToInt();
                    //UnityEngine.Debug.Log("n_pow(1)=" + n_pow.ToString());
                    if (n_pow > 350)
                    {
                        if (exp_sign < 0)
                        {
                            n_pow = -400;
                            if (dot_pos < 0)
                            {
                                dot_pos = exp_pos;
                            }
                            return(true);  // underflow, round to zero.
                        }
                        else
                        {
                            return(false); // overflow
                        }
                    }
                }
                n_pow *= exp_sign;
            }
            else
            {
                // no [e/E+-[int]] part
                exp_pos = length;
            }

            if (dot_pos < 0)
            {
                dot_pos = exp_pos;
            }

            //UnityEngine.Debug.Log("ParseFloatFormat=" + true.ToString());

            return(true);
        }