| Index: runtime/bin/dartutils.cc
|
| ===================================================================
|
| --- runtime/bin/dartutils.cc (revision 40060)
|
| +++ runtime/bin/dartutils.cc (working copy)
|
| @@ -869,6 +869,137 @@
|
| }
|
|
|
|
|
| +static bool IsHexDigit(char c) {
|
| + return (('0' <= c) && (c <= '9'))
|
| + || (('A' <= c) && (c <= 'F'))
|
| + || (('a' <= c) && (c <= 'f'));
|
| +}
|
| +
|
| +
|
| +static int HexDigitToInt(char c) {
|
| + if (('0' <= c) && (c <= '9')) return c - '0';
|
| + if (('A' <= c) && (c <= 'F')) return 10 + (c - 'A');
|
| + return 10 + (c - 'a');
|
| +}
|
| +
|
| +
|
| +Dart_CObject* CObject::NewBigint(const char* hex_value) {
|
| + if (hex_value == NULL) {
|
| + return NULL;
|
| + }
|
| + bool neg = false;
|
| + if (hex_value[0] == '-') {
|
| + neg = true;
|
| + hex_value++;
|
| + }
|
| + if ((hex_value[0] != '0') ||
|
| + ((hex_value[1] != 'x') && (hex_value[1] != 'X'))) {
|
| + return NULL;
|
| + }
|
| + hex_value += 2;
|
| + intptr_t hex_i = strlen(hex_value); // Terminating byte excluded.
|
| + if (hex_i == 0) {
|
| + return NULL;
|
| + }
|
| + const int kBitsPerHexDigit = 4;
|
| + const int kHexDigitsPerDigit = 8;
|
| + const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit;
|
| + const intptr_t len = (hex_i + kHexDigitsPerDigit - 1) / kHexDigitsPerDigit;
|
| + Dart_CObject* cobject = New(Dart_CObject_kBigint);
|
| + cobject->value.as_bigint.digits = NewUint32Array(len);
|
| + uint32_t* digits = reinterpret_cast<uint32_t*>(
|
| + cobject->value.as_bigint.digits->value.as_typed_data.values);
|
| + intptr_t used = 0;
|
| + uint32_t digit = 0;
|
| + intptr_t bit_i = 0;
|
| + while (--hex_i >= 0) {
|
| + if (!IsHexDigit(hex_value[hex_i])) {
|
| + return NULL;
|
| + }
|
| + digit += HexDigitToInt(hex_value[hex_i]) << bit_i;
|
| + bit_i += kBitsPerHexDigit;
|
| + if (bit_i == kBitsPerDigit) {
|
| + bit_i = 0;
|
| + digits[used++] = digit;
|
| + digit = 0;
|
| + }
|
| + }
|
| + if (bit_i != 0) {
|
| + digits[used++] = digit;
|
| + }
|
| + while ((used > 0) && (digits[used - 1] == 0)) {
|
| + used--;
|
| + }
|
| + cobject->value.as_bigint.used = used;
|
| + if (used == 0) {
|
| + neg = false;
|
| + }
|
| + cobject->value.as_bigint.neg = neg;
|
| + return cobject;
|
| +}
|
| +
|
| +
|
| +static char IntToHexDigit(int i) {
|
| + ASSERT(0 <= i && i < 16);
|
| + if (i < 10) return static_cast<char>('0' + i);
|
| + return static_cast<char>('A' + (i - 10));
|
| +}
|
| +
|
| +
|
| +char* CObject::BigintToHexValue(Dart_CObject* bigint) {
|
| + ASSERT(bigint->type == Dart_CObject_kBigint);
|
| + const intptr_t used = bigint->value.as_bigint.used;
|
| + if (used == 0) {
|
| + const char* zero = "0x0";
|
| + const size_t len = strlen(zero) + 1;
|
| + char* hex_value = reinterpret_cast<char*>(malloc(len));
|
| + strncpy(hex_value, zero, len);
|
| + return hex_value;
|
| + }
|
| + const int kBitsPerHexDigit = 4;
|
| + const int kHexDigitsPerDigit = 8;
|
| + const intptr_t kMaxUsed = (kIntptrMax - 4) / kHexDigitsPerDigit;
|
| + if (used > kMaxUsed) {
|
| + return NULL;
|
| + }
|
| + intptr_t hex_len = (used - 1) * kHexDigitsPerDigit;
|
| + const uint32_t* digits = reinterpret_cast<uint32_t*>(
|
| + bigint->value.as_bigint.digits->value.as_typed_data.values);
|
| + // The most significant digit may use fewer than kHexDigitsPerDigit digits.
|
| + uint32_t digit = digits[used - 1];
|
| + ASSERT(digit != 0); // Value must be clamped.
|
| + while (digit != 0) {
|
| + hex_len++;
|
| + digit >>= kBitsPerHexDigit;
|
| + }
|
| + const bool neg = bigint->value.as_bigint.neg;
|
| + // Add bytes for '0x', for the minus sign, and for the trailing \0 character.
|
| + const int32_t len = (neg ? 1 : 0) + 2 + hex_len + 1;
|
| + char* hex_value = reinterpret_cast<char*>(malloc(len));
|
| + intptr_t pos = len;
|
| + hex_value[--pos] = '\0';
|
| + for (intptr_t i = 0; i < (used - 1); i++) {
|
| + digit = digits[i];
|
| + for (intptr_t j = 0; j < kHexDigitsPerDigit; j++) {
|
| + hex_value[--pos] = IntToHexDigit(digit & 0xf);
|
| + digit >>= kBitsPerHexDigit;
|
| + }
|
| + }
|
| + digit = digits[used - 1];
|
| + while (digit != 0) {
|
| + hex_value[--pos] = IntToHexDigit(digit & 0xf);
|
| + digit >>= kBitsPerHexDigit;
|
| + }
|
| + hex_value[--pos] = 'x';
|
| + hex_value[--pos] = '0';
|
| + if (neg) {
|
| + hex_value[--pos] = '-';
|
| + }
|
| + ASSERT(pos == 0);
|
| + return hex_value;
|
| +}
|
| +
|
| +
|
| Dart_CObject* CObject::NewDouble(double value) {
|
| Dart_CObject* cobject = New(Dart_CObject_kDouble);
|
| cobject->value.as_double = value;
|
| @@ -910,6 +1041,15 @@
|
| }
|
|
|
|
|
| +Dart_CObject* CObject::NewUint32Array(intptr_t length) {
|
| + Dart_CObject* cobject = New(Dart_CObject_kTypedData, 4*length);
|
| + cobject->value.as_typed_data.type = Dart_TypedData_kUint32;
|
| + cobject->value.as_typed_data.length = length;
|
| + cobject->value.as_typed_data.values = reinterpret_cast<uint8_t*>(cobject + 1);
|
| + return cobject;
|
| +}
|
| +
|
| +
|
| Dart_CObject* CObject::NewExternalUint8Array(
|
| intptr_t length, uint8_t* data, void* peer,
|
| Dart_WeakPersistentHandleFinalizer callback) {
|
|
|