txSlot* fx_Date_prototype_getUTC_aux(txMachine* the, txTimeDescription* td) { txSlot* slot = fxCheckDate(the, mxThis); txNumber number; c_time_t time; txInteger year = 0; if (!slot) mxTypeError("this is no date"); number = slot->value.number; if (c_isnan(number)) { mxResult->value.number = C_NAN; mxResult->kind = XS_NUMBER_KIND; return C_NULL; } c_memset(td, 0, sizeof(txTimeDescription)); td->tm.tm_mday = 1; td->ms = (int)c_floor(c_fmod(number, 1000.0)); number /= 1000.0; //if ((number < gxMinTime) || (gxMaxTime < number)) // mxTypeError("invalid time"); if(number > TIME_2032) { // 2032 <= number <= 2099 year = (int)((number - TIME_2032)/TIME_FourYear); number -= TIME_FourYear * year; year *= 4; } time = (c_time_t)c_floor(number); td->tm = *c_gmtime(&time); td->tm.tm_year += year; if( (td->ms < 0) && (td->ms > -1000) ) td->ms = 1000 + td->ms; mxResult->kind = XS_INTEGER_KIND; return slot; }
txInteger fxToInteger(txMachine* the, txSlot* theSlot) { #if mxOptimize if (XS_INTEGER_KIND == theSlot->kind) return theSlot->value.integer; // this is the case over 90% of the time, so avoid the switch #endif again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: case XS_NULL_KIND: theSlot->kind = XS_INTEGER_KIND; theSlot->value.integer = 0; break; case XS_BOOLEAN_KIND: theSlot->kind = XS_INTEGER_KIND; if (theSlot->value.boolean == 0) theSlot->value.integer = 0; else theSlot->value.integer = 1; break; case XS_INTEGER_KIND: break; case XS_NUMBER_KIND: theSlot->kind = XS_INTEGER_KIND; switch (c_fpclassify(theSlot->value.number)) { case C_FP_INFINITE: case C_FP_NAN: case C_FP_ZERO: theSlot->value.integer = 0; break; default: { #define MODULO 4294967296.0 txNumber aNumber = c_fmod(c_trunc(theSlot->value.number), MODULO); if (aNumber >= MODULO / 2) aNumber -= MODULO; else if (aNumber < -MODULO / 2) aNumber += MODULO; theSlot->value.integer = (txInteger)aNumber; } break; } break; case XS_STRING_KIND: case XS_STRING_X_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1); goto again; case XS_SYMBOL_KIND: mxTypeError("Cannot coerce symbol to integer"); break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_NUMBER_HINT); goto again; default: mxTypeError("Cannot coerce to integer"); break; } return theSlot->value.integer; }
void fx_Number_prototype_toString(txMachine* the) { char buffer[256]; txInteger radix; txSlot* slot = fxCheckNumber(the, mxThis); if (!slot) mxTypeError("this is no number"); if (mxArgc > 0) { radix = fxToInteger(the, mxArgv(0)); if (radix) { if ((radix < 2) || (36 < radix)) mxRangeError("invalid radix"); } else radix = 10; } else radix = 10; mxResult->kind = slot->kind; mxResult->value = slot->value; if (radix == 10) fxToString(the, mxResult); else { static char gxDigits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; txString string = buffer + sizeof(buffer); txNumber value; txBoolean minus; value = mxResult->value.number; switch (c_fpclassify(value)) { case C_FP_INFINITE: if (value < 0) fxCopyStringC(the, mxResult, "-Infinity"); else fxCopyStringC(the, mxResult, "Infinity"); break; case C_FP_NAN: fxCopyStringC(the, mxResult, "NaN"); break; case C_FP_ZERO: fxCopyStringC(the, mxResult, "0"); break; default: *(--string) = 0; if (value < 0) { minus = 1; value = -value; } else minus = 0; do { *(--string) = gxDigits[(txInteger)c_fmod(value, radix)]; value = value / radix; } while (value >= 1); if (minus) *(--string) = '-'; fxCopyStringC(the, mxResult, string); } } }
void fx_Number_toString(txMachine* the) { txSlot* aNumber; txSlot* aProperty; txInteger aRadix; aNumber = fxGetInstance(the, mxThis); mxCheckNumber(aNumber); aProperty = aNumber->next; if (mxArgc > 0) { aRadix = fxToInteger(the, mxArgv(0)); if (aRadix) { if ((aRadix < 2) || (36 < aRadix)) mxDebug0(the, XS_RANGE_ERROR, "invalid radix"); } else aRadix = 10; } else aRadix = 10; mxResult->kind = aProperty->kind; mxResult->value = aProperty->value; if (aRadix == 10) fxToString(the, mxResult); else { static char gxDigits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char aBuffer[256]; txString aString; txNumber aValue; txBoolean aMinus; fxToNumber(the, mxResult); aString = aBuffer + sizeof(aBuffer); *(--aString) = 0; aValue = mxResult->value.number; if (aValue < 0) { aMinus = 1; aValue = -aValue; } else aMinus = 0; do { *(--aString) = gxDigits[(txInteger)c_fmod(aValue, aRadix)]; aValue = aValue / aRadix; } while (aValue >= 1); if (aMinus) *(--aString) = '-'; fxCopyStringC(the, mxResult, aString); } }
txUnsigned fxToUnsigned(txMachine* the, txSlot* theSlot) { txUnsigned result; again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: case XS_NULL_KIND: theSlot->kind = XS_INTEGER_KIND; result = theSlot->value.integer = 0; break; case XS_BOOLEAN_KIND: theSlot->kind = XS_INTEGER_KIND; if (theSlot->value.boolean == 0) result = theSlot->value.integer = 0; else result = theSlot->value.integer = 1; break; case XS_INTEGER_KIND: if (theSlot->value.integer >= 0) return (txUnsigned)theSlot->value.integer; theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = theSlot->value.integer; // continue case XS_NUMBER_KIND: theSlot->kind = XS_INTEGER_KIND; switch (c_fpclassify(theSlot->value.number)) { case C_FP_INFINITE: case C_FP_NAN: case C_FP_ZERO: result = theSlot->value.integer = 0; break; default: { #define MODULO 4294967296.0 txNumber aNumber = c_fmod(c_trunc(theSlot->value.number), MODULO); if (aNumber < 0) aNumber += MODULO; result = (txUnsigned)aNumber; if (((txInteger)result) >= 0) { theSlot->kind = XS_INTEGER_KIND; theSlot->value.integer = (txInteger)result; } else { theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = aNumber; } } break; } break; case XS_STRING_KIND: case XS_STRING_X_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1); goto again; case XS_SYMBOL_KIND: result = 0; mxTypeError("Cannot coerce symbol to unsigned"); break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_NUMBER_HINT); goto again; default: result = 0; mxTypeError("Cannot coerce to unsigned"); break; } return result; }