Пример #1
0
Файл: VM.cpp Проект: Gwill/luna
    void VM::Concat(Value *dst, Value *op1, Value *op2)
    {
        if (op1->type_ == ValueT_String && op2->type_ == ValueT_String)
        {
            dst->str_ = state_->GetString(op1->str_->GetStdString() +
                                          op2->str_->GetCStr());
        }
        else if (op1->type_ == ValueT_String && op2->type_ == ValueT_Number)
        {
            dst->str_ = state_->GetString(op1->str_->GetCStr() +
                                          NumberToStr(op2));
        }
        else if (op1->type_ == ValueT_Number && op2->type_ == ValueT_String)
        {
            dst->str_ = state_->GetString(NumberToStr(op1) +
                                          op2->str_->GetCStr());
        }
        else
        {
            auto pos = GetCurrentInstructionPos();
            throw RuntimeException(pos.first, pos.second, op1, op2, "concat");
        }

        dst->type_ = ValueT_String;
    }
Пример #2
0
// binary string to hexadecimal string
char* BinStrToHexStr(char* binStr, char* hexStr)
{
    int i, j, t;
    Number binNum;
    Number hexNum;

    StrToNumber(binStr, &binNum);

    hexNum.sign = binNum.sign;
    hexNum.len = (int)ceil(binNum.len / 4.0);

    for (i = 0; i < hexNum.len; i++)
    {
        j = 4 * i;

        t = binNum.value[j];

        if (j + 1 < binNum.len)
            t += 2 * binNum.value[j + 1];

        if (j + 2 < binNum.len)
            t += 4 * binNum.value[j + 2];

        if (j + 3 < binNum.len)
            t += 8 * binNum.value[j + 3];

        hexNum.value[i] = t;
    }

    return NumberToStr(&hexNum, hexStr);
}
Пример #3
0
// change type: BigInt to string(radix 10)
char* BigIntToStr(BigInt* a, char* s)
{
    char buf[BUFFER_SIZE];
    Number binNum;

    BigIntToBinNum(a, &binNum);     // BigInt to Number
    NumberToStr(&binNum, buf);      // Number to string

    return ChangeStringRadix(buf, 2, 10, s);  // string radix 2 to 10
}
Пример #4
0
// change string radix from srcRadix to dstRadix
char* ChangeStringRadix(char* str, int srcRadix, int dstRadix, char* resultStr)
{
    if (srcRadix < dstRadix)
    {
        char hexStr[BUFFER_SIZE];

        ChangeStringRadix(str, srcRadix, 2, resultStr);  // srcRadix to radix 2
        BinStrToHexStr(resultStr, hexStr);               // radix 2 to 16

        // radix 16 to dstRadix
        return ChangeStringRadix(hexStr, 16, dstRadix, resultStr);
    }

    if (srcRadix == dstRadix)
    {
        return strcpy(resultStr, str);
    }

    else  // srcRadix > dstRadix
    {
        int i, t;
        Number dividend;
        Number quotient;
        Number resultNum;

        // string to Number
        StrToNumber(str, &dividend);

        resultNum.len = 0;
        resultNum.sign = dividend.sign;

        while (dividend.len > 0)
        {
            quotient.len = dividend.len;

            // simulate the way we do division
            // when the cycle is end, t is the remainder
            for (t = 0, i = dividend.len - 1; i >= 0; i--)
            {
                t = t * srcRadix + dividend.value[i];
                quotient.value[i] = t / dstRadix;
                t = t % dstRadix;
            }

            // save the remainder
            resultNum.value[resultNum.len++] = t;

            // filter the unnecessary 0 in quotient
            for (i = quotient.len - 1; i >= 0 && quotient.value[i] == 0; i--);

            // set the next dividend length
            dividend.len = i + 1;

            // let the quotient be the next divident
            for (i = 0; i < dividend.len; i++)
            {
                dividend.value[i] = quotient.value[i];
            }
        }

        return NumberToStr(&resultNum, resultStr);
    }
}
Пример #5
0
/* Str format(...)
   Format a string based on a format string which may contain formatting
   sequences of form {...}; these correspond to the arguments of the method.
   The base string object represents the format string. */
AValue AFormat(AThread *t, AValue *frame)
{
    int fi;      /* Format string index */
    int ai;      /* Argument index */
    int fmtLen;  /* Format string length */
    FormatOutput output;

    AExpectStr(t, frame[0]);

    output.t = t;
    output.index = 0;
    output.len = FORMAT_BUF_SIZE;
    output.str = &frame[2];

    fmtLen = AStrLen(frame[0]);
    ai = 0;

    /* IDEA: Refactor this into multiple functions. */

    /* Iterate over the format string. Handle { sequences and copy other
       characters directly to the output buffer (} may be duplicated). */
    for (fi = 0; fi < fmtLen; fi++) {
        int ch = AStrItem(frame[0], fi);
        if (ch == '{') {
            if (fi == fmtLen - 1 || AStrItem(frame[0], fi + 1) == '{') {
                /* Literal '{'. */
                fi++;
                Append(&output, ch);
            } else {
                /* A format sequence {...}. */
                int negAlign = FALSE;
                int align = 0;
                int oldInd;
                int oldOutInd;
                AValue arg;

                fi++;
                oldInd = fi;

                /* Parse alignment */
                if (fi < fmtLen && AStrItem(frame[0], fi) == '-'
                    && AIsDigit(AStrItem(frame[0], fi + 1))) {
                    negAlign = TRUE;
                    fi++;
                }
                if (fi < fmtLen && AIsDigit(AStrItem(frame[0], fi))) {
                    do {
                        align = align * 10 + AStrItem(frame[0], fi) - '0';
                        fi++;
                    } while (fi < fmtLen && AIsDigit(AStrItem(frame[0], fi)));
                    if (AStrItem(frame[0], fi) != ':') {
                        fi = oldInd;
                        align = 0;
                    } else
                        fi++;
                }

                oldOutInd = output.index & ~WIDE_BUF_FLAG;

                if (ai >= AArrayLen(frame[1]))
                    ARaiseValueError(t, "Too few arguments");

                arg = AArrayItem(frame[1], ai);
                if (AIsInstance(arg)
                    && AStrItem(frame[0], fi) != '}'
                    && AMember(t, arg, "_format") != AError) {
                    int i;
                    oldInd = fi;
                    while (fi <= fmtLen && AStrItem(frame[0], fi) != '}')
                        fi++;
                    if (fi >= fmtLen)
                        ARaiseValueError(t, "Unterminated format");
                    frame[3] = AArrayItem(frame[1], ai);
                    frame[4] = ASubStr(t, frame[0], oldInd, fi);
                    frame[3] = ACallMethod(t, "_format", 1, frame + 3);
                    if (AIsError(frame[3]))
                        return AError;
                    AExpectStr(t, frame[3]);
                    for (i = 0; i < AStrLen(frame[3]); i++)
                        Append(&output, AStrItem(frame[3], i));
                } else {
                    /* Either format an Int/Float or use the default conversion
                       by calling std::Str. */
                    int minNumLen = 0;
                    int fractionLen = 0;
                    int optFractionLen = 0;
                    int expLen = 0;
                    int fraction = FALSE;
                    int scientific = FALSE;
                    int plusExp = FALSE;
                    int expChar = ' ';

                    while (fi < fmtLen &&
                           (ch = AStrItem(frame[0], fi)) != '}') {
                        if (ch == '0') {
                            if (scientific)
                                expLen++;
                            else if (fraction)
                                fractionLen++;
                            else
                                minNumLen++;
                        } else if (ch == '.')
                            fraction = TRUE;
                        else if (ch == 'e' || ch == 'E') {
                            scientific = TRUE;
                            expChar = ch;
                        } else if (ch == '+' && scientific)
                            plusExp = TRUE;
                        else if (ch == '#' && fraction && !scientific) {
                            fractionLen++;
                            optFractionLen++;
                        } else
                            ARaiseValueError(t, "Invalid character in format");
                        fi++;
                    }

                    if (scientific)
                        NumberToScientific(&output, arg, fractionLen, expLen,
                                           expChar, plusExp, optFractionLen);
                    else if (minNumLen > 0 || fraction)
                        NumberToStr(&output, arg, minNumLen, fractionLen,
                                    optFractionLen);
                    else {
                        /* Not a number formatting sequence. Use std::Str to
                           convert the argument. */
                        int i;

                        frame[3] = arg;
                        frame[3] = AStdStr(t, &frame[3]);
                        if (AIsError(frame[3]))
                            return AError;

                        for (i = 0; i < AStrLen(frame[3]); i++)
                            Append(&output, AStrItem(frame[3], i));
                    }
                }

                if (fi >= fmtLen)
                    ARaiseValueError(t, "Unterminated format");

                align -= (output.index & ~WIDE_BUF_FLAG) - oldOutInd;
                if (align > 0) {
                    int i;

                    for (i = 0; i < align; i++)
                        Append(&output, ' ');

                    if (!negAlign) {
                        if (output.index < FORMAT_BUF_SIZE) {
                            AMoveMem(output.buf + oldOutInd + align,
                                    output.buf + oldOutInd,
                                    output.index - oldOutInd - align);
                            for (i = 0; i < align; i++)
                                output.buf[oldOutInd + i] = ' ';
                        } else {
                            for (i = (output.index & ~WIDE_BUF_FLAG) - 1;
                                 i >= oldOutInd + align; i--)
                                ASetStrItem(frame[2], i,
                                            AStrItem(frame[2], i - align));
                            for (i = 0; i < align; i++)
                                ASetStrItem(frame[2], oldOutInd + i, ' ');
                        }
                    }
                }
                ai++;
            }
        } else if (ch == '}') {
            /* Literal '}' can be duplicated (but does not need to be). */
            if (fi < fmtLen - 1 && AStrItem(frame[0], fi + 1) == '}')
                fi++;
            Append(&output, ch);
        } else
            Append(&output, ch);
    }

    if (ai < AArrayLen(frame[1]))
        ARaiseValueError(t, "Too many arguments");

    if (output.index <= FORMAT_BUF_SIZE) {
        /* The output contains only narrow characters (since the index does not
           have the WIDE_BUF_FLAG flag) and is short enough to not require a
           heap-allocated buffer. Create a string based on the internal
           buffer. */
        AValue res = AMakeEmptyStr(t, output.index);
        ACopyMem(AGetStrElem(res), output.buf, output.index);
        return res;
    } else {
        /* The output is stored in a heap-allocated buffer (represented as a
           Str object). Return the initialized part of the buffer. */
        return ASubStr(t, frame[2], 0, output.index & ~WIDE_BUF_FLAG);
    }
}
Пример #6
0
/* Convert a number using a scientific format (e.g. 0.00e+00). The num argument
   is the number to convert. The argument numFrac is the number of digits in
   the fraction, expLen is the number of digits in the exponent, plusExp
   defines whether to prefix a positive exponent always with a '+', and optFrac
   speficies the number of fraction digits that are only generated if they are
   not zeroes. */
static void NumberToScientific(FormatOutput *output, AValue num, int numFrac,
                                int expLen, int expChar, ABool plusExp, int
                                optFrac)
{
    /* FIX: Use sprintf for the conversion for better accuracy. */

    double f = AGetFloat(output->t, num);
    int exp = 0;
    ABool sign = f < 0.0;
    int i;
    char s[NUM_BUF_SIZE];
    int si;
    int s0;

    /* Handle infinities and NaN's as special cases. */
    if (AIsNaN(f)) {
        AppendStr(output, "nan");
        return;
    } else if (AIsInf(f)) {
        if (f > 0.0)
            AppendStr(output, "inf");
        else
            AppendStr(output, "-inf");
        return;
    }

    if (sign)
        f = -f;

    if (f != 0.0) {
        double max = 10.0 - 0.5 * pow(10.0, -numFrac);
        double min = 1.0 - 0.5 * pow(10.0, -numFrac);
        while (f >= max) {
            f /= 10.0;
            exp++;
        }
        while (f < min) {
            f *= 10.0;
            exp--;
        }
    }

    f = floor(f * pow(10.0, numFrac) + 0.5);

    if (numFrac >= NUM_BUF_SIZE - 2)
        ARaiseValueError(output->t, "Formatted Float is too long");

    si = 0;
    for (i = 0; i <= numFrac; i++) {
        int d = (int)fmod(f, 10.0);
        s[si++] = '0' + d;
        f /= 10.0;
    }

    s0 = 0;
    while (optFrac > 0 && s0 < si && s[s0] == '0') {
        s0++;
        optFrac--;
        numFrac--;
    }

    if (sign)
        AppendCh(output, '-');
    AppendCh(output, s[si - 1]);
    if (numFrac > 0)
        AppendCh(output, '.');
    for (i = si - 2; i >= s0; i--)
        AppendCh(output, s[i]);
    AppendCh(output, expChar);
    if (plusExp && exp >= 0)
        AppendCh(output, '+');
    NumberToStr(output, AMakeInt(output->t, exp), expLen, 0, 0);
}