예제 #1
0
파일: Numeric.cs 프로젝트: retahc/old-code
 public virtual RArray Coerce(object o)
 {
     if (ruby.ClassOf(o) == Class)
     {
         return(RArray.AssocNew(ruby, Instanciate(o), this));
     }
     return(RArray.AssocNew(ruby, RFloat.Float(ruby, o), ToFloat()));
 }
예제 #2
0
        internal static object sprintf(RBasic r, params object[] args)
        {
            NetRuby ruby = r.ruby;

            PFlag  flags   = PFlag.NONE;
            bool   tainted = false;
            object ofmt;
            int    nextarg = getarg(args, 0, out ofmt);

            if (ofmt is RBasic)
            {
                tainted = ((RBasic)ofmt).IsTainted;
            }
            string fmt = ofmt.ToString();
            string result = String.Empty;
            int    width, prec;

            for (int i = 0; i < fmt.Length; i++)
            {
                int n, ix;
                for (ix = i; ix < fmt.Length && fmt[ix] != '%'; ix++)
                {
                    ;
                }
                result += fmt.Substring(i, ix - i);
                if (ix >= fmt.Length)
                {
                    break;
                }
                i     = ix + 1;
                width = prec = -1;
retry:
                switch (fmt[i])
                {
                case ' ':
                    flags |= PFlag.SPACE;
                    i++;
                    goto retry;

                case '#':
                    flags |= PFlag.SHARP;
                    i++;
                    goto retry;

                case '+':
                    flags |= PFlag.PLUS;
                    i++;
                    goto retry;

                case '-':
                    flags |= PFlag.MINUS;
                    i++;
                    goto retry;

                case '0':
                    flags |= PFlag.ZERO;
                    i++;
                    goto retry;

                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    n = 0;
                    for (; i < fmt.Length && Char.IsDigit(fmt[i]); i++)
                    {
                        n = 10 * n + (int)Char.GetNumericValue(fmt[i]);
                    }
                    if (i >= fmt.Length)
                    {
                        throw new ArgumentException("malformed format string - %%[0-9]");
                    }
                    if (fmt[i] == '$')
                    {
                        nextarg = n;
                        i++;
                        goto retry;
                    }
                    width  = n;
                    flags |= PFlag.WIDTH;
                    goto retry;

                case '*':
                    if ((flags & PFlag.WIDTH) != 0)
                    {
                        throw new ArgumentException("width given twice");
                    }
                    flags |= PFlag.WIDTH;
                    width  = getaster(fmt, ref i, ref nextarg, args);
                    if (width < 0)
                    {
                        flags |= PFlag.MINUS;
                        width  = -width;
                    }
                    i++;
                    goto retry;

                case '.':
                    if ((flags & PFlag.PREC) != 0)
                    {
                        throw new ArgumentException("precision given twice");
                    }
                    flags |= PFlag.PREC;
                    prec   = 0;
                    i++;
                    if (fmt[i] == '*')
                    {
                        prec = getaster(fmt, ref i, ref nextarg, args);
                        if (prec < 0)          /* ignore negative precision */
                        {
                            flags &= ~PFlag.PREC;
                        }
                        i++;
                        goto retry;
                    }
                    for (; i < fmt.Length && Char.IsDigit(fmt[i]); i++)
                    {
                        prec = 10 * prec + (int)Char.GetNumericValue(fmt[i]);
                    }
                    if (i >= fmt.Length)
                    {
                        throw new ArgumentException("malformed format string - %%.[0-9]");
                    }
                    goto retry;

                case '\n':
                    i--;
                    goto case '%';

                case '\0':
                case '%':
                    if (flags != PFlag.NONE)
                    {
                        throw new ArgumentException("illegal format character - %%");
                    }
                    result += '%';
                    break;

                case 'c': {
                    object val;
                    nextarg = getarg(args, nextarg, out val);
                    if ((flags & PFlag.MINUS) == 0)
                    {
                        if (width > 0)
                        {
                            result = result.PadRight(result.Length + width);
                        }
                    }
                    char c = (char)Convert.ToInt32(val);
                    result += c;
                    result  = result.PadRight(result.Length + width);
                    break;
                }

                case 's': {
                    object arg;
                    nextarg = getarg(args, nextarg, out arg);
                    RString rs = RString.AsRString(ruby, arg);
                    if (rs.IsTainted)
                    {
                        tainted = true;
                    }
                    int len = rs.Length;
                    if ((flags & PFlag.PREC) != 0)
                    {
                        if (prec < len)
                        {
                            len = prec;
                        }
                    }
                    if ((flags & PFlag.WIDTH) != 0)
                    {
                        if (width > len)
                        {
                            width -= len;
                            if ((flags & PFlag.MINUS) == 0)
                            {
                                if (width > 0)
                                {
                                    result = result.PadRight(result.Length + width);
                                }
                            }
                            result += rs.ToString();
                            if ((flags & PFlag.MINUS) != 0)
                            {
                                if (width > 0)
                                {
                                    result = result.PadRight(result.Length + width);
                                }
                            }
                            break;
                        }
                    }
                    result += rs.ToString().Substring(0, len);
                    break;
                }

                case 'd':
                case 'i':
                case 'o':
                case 'x':
                case 'X':
                case 'b':
                case 'u': {
                    char   sc = '\0';
                    char   ch = fmt[i];
                    object val;
                    nextarg = getarg(args, nextarg, out val);
                    bool   sign   = false;
                    bool   bignum = false;
                    long   num    = 0;
                    string prefix = String.Empty;
                    string s      = String.Empty;
                    switch (ch)
                    {
                    case 'd':
                    case 'i':
                        sign = true; break;

                    case 'o':
                    case 'x':
                    case 'X':
                    case 'b':
                    case 'u':
                    default:
                        if ((flags & (PFlag.PLUS | PFlag.SPACE)) != 0)
                        {
                            sign = true;
                        }
                        break;
                    }
                    if ((flags & PFlag.SHARP) != 0)
                    {
                        if (fmt[i] == 'o')
                        {
                            prefix = "0";
                        }
                        else if (fmt[i] == 'x')
                        {
                            prefix = "0x";
                        }
                        else if (fmt[i] == 'X')
                        {
                            prefix = "0X";
                        }
                        else if (fmt[i] == 'b')
                        {
                            prefix = "0b";
                        }
                        if (prefix.Length > 0)
                        {
                            width -= prefix.Length;
                        }
                    }
bin_retry:
                    if (val is RFloat)
                    {
                        val = ((RFloat)val).ToInteger();
                        goto bin_retry;
                    }
                    else if (val is double)
                    {
                        val = RFloat.ToInteger(ruby, (double)val);
                        goto bin_retry;
                    }
                    else if (val is string)
                    {
                        val = RInteger.StringToInteger(ruby, (string)val, 0);
                        goto bin_retry;
                    }
                    else if (val is RString)
                    {
                        val = ((RString)val).ToInteger();
                        goto bin_retry;
                    }
                    else if (val is int)
                    {
                        num = (long)(int)val;
                    }
                    else if (val is long)
                    {
                        num = (long)val;
                    }
                    else if (val is uint)
                    {
                        num = (long)(uint)val;
                    }
                    else if (val is RBignum)
                    {
                        bignum = true;
                    }
                    else
                    {
                        num = RInteger.ToLong(ruby, val);
                    }
                    int bas = 0;
                    if (ch == 'u' || ch == 'd' || ch == 'i')
                    {
                        bas = 10;
                    }
                    else if (ch == 'x' || ch == 'X')
                    {
                        bas = 16;
                    }
                    else if (ch == 'o')
                    {
                        bas = 8;
                    }
                    else if (ch == 'b')
                    {
                        bas = 2;
                    }
                    if (!bignum)
                    {
                        if (sign)
                        {
                            if (ch == 'i')
                            {
                                ch = 'd';            /* %d and %i are identical */
                            }
                            if (num < 0)
                            {
                                num = -num;
                                sc  = '-';
                                width--;
                            }
                            else if ((flags & PFlag.PLUS) != 0)
                            {
                                sc = '+';
                                width--;
                            }
                            else if ((flags & PFlag.SPACE) != 0)
                            {
                                sc = ' ';
                                width--;
                            }
                            s = Convert.ToString(num, bas);
                            goto format_integer;
                        }
                        else
                        {
                            s = Convert.ToString(num, bas);
                            goto format_integer;
                        }
                    }
                    // bignum
                    RBignum big = (RBignum)val;
                    if (sign)
                    {
                        s = big.ToRString(bas).ToString();
                        if (s[0] == '-')
                        {
                            s  = s.Substring(1);
                            sc = '-';
                            width--;
                        }
                        else if ((flags & PFlag.PLUS) != 0)
                        {
                            sc = '+';
                            width--;
                        }
                        else if ((flags & PFlag.SPACE) != 0)
                        {
                            sc = ' ';
                            width--;
                        }
                        goto format_integer;
                    }
                    if (big.Sign == false)
                    {
                        big = (RBignum)big.Clone();
                        big.TwoComp();
                    }
                    s = big.ToRString(bas).ToString();
                    if (s[0] == '-')
                    {
                        s = remove_sign_bits(s.Substring(1), bas);
                        StringBuilder sb = new StringBuilder(s.Length + 3);
                        sb.Append("..");
                        switch (bas)
                        {
                        case 16:
                            if (s[0] != 'f')
                            {
                                sb.Append('f');
                            }
                            break;

                        case 8:
                            if (s[0] != '7')
                            {
                                sb.Append('7');
                            }
                            break;
                        }
                        sb.Append(s);
                        s = sb.ToString();
                    }

format_integer:
                    int pos = -1;
                    int len = s.Length;

                    if (ch == 'X')
                    {
                        s = s.ToUpper();
                    }
                    if (prec < len)
                    {
                        prec = len;
                    }
                    width -= prec;
                    if ((flags & (PFlag.ZERO | PFlag.MINUS)) == 0 && s[0] != '.')
                    {
                        if (width > 0)
                        {
                            s = s.PadLeft(s.Length + width);
                        }
                    }
                    if (sc != '\0')
                    {
                        result += sc;
                    }
                    if (prefix.Length > 0)
                    {
                        result += prefix;
                        if (pos != 0)
                        {
                            pos += prefix.Length;
                        }
                    }
                    if ((flags & PFlag.MINUS) == 0)
                    {
                        char c = ' ';

                        if (s[0] == '.')
                        {
                            c = '.';
                            if ((flags & PFlag.PREC) != 0 && prec > len)
                            {
                                pos = result.Length;
                            }
                            else
                            {
                                pos = result.Length + 2;
                            }
                        }
                        else if ((flags & PFlag.ZERO) != 0)
                        {
                            c = '0';
                        }
                        if (width > 0)
                        {
                            result = result.PadRight(result.Length + width, c);
                        }
                    }
                    if (len < prec)
                    {
                        if (width > 0)
                        {
                            result = result.PadRight(result.Length + (prec - len), (s[0] == '.'?'.':'0'));
                        }
                    }
                    result += s;
                    if (width > 0)
                    {
                        result = result.PadRight(result.Length + width);
                    }
                    break;
                }

                case 'f':
                case 'g':
                case 'G':
                case 'e':
                case 'E': {
                    object val;
                    nextarg = getarg(args, nextarg, out val);
                    double fval = 0.0;

                    if (val is RString || val is string)
                    {
                        fval = Convert.ToDouble(((RString)val).ToString());
                    }
                    else if (val is int || val is long || val is uint)
                    {
                        fval = Convert.ToDouble(val);
                    }
                    else if (val is RFloat)
                    {
                        fval = ((RFloat)val).Double;
                    }
                    else if (val is double)
                    {
                        fval = (double)val;
                    }

                    string buf;
                    if (fmt[i] != 'e' && fmt[i] != 'E')
                    {
                        buf = new String(fmt[i], 1);
                        if ((flags & PFlag.PREC) != 0)
                        {
                            buf += prec.ToString();
                        }
                    }
                    else
                    {
                        buf = "#";
                        if ((flags & PFlag.SHARP) != 0)
                        {
                            buf += ".0";
                        }
                        buf += fmt[i];
                        if ((flags & PFlag.PLUS) != 0)
                        {
                            buf += '+';
                        }
                        if ((flags & PFlag.PREC) != 0)
                        {
                            buf += new String('0', prec);
                        }
                        else
                        {
                            buf += '0';
                        }
                    }
                    buf = fval.ToString(buf);
                    if ((flags & PFlag.WIDTH) != 0)
                    {
                    }
                    result += buf;
                    break;
                }

                default:
                    throw new ArgumentException(String.Format("malformed format string - %{0}", fmt[i]));
                }
                flags = PFlag.NONE;
            }
            if (tainted)
            {
                return(new RString(ruby, result, true));
            }
            return(result);
        }