ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, /**< string represenation of the BigInt */
                          lit_utf8_size_t size, /**< string size */
                          uint32_t options) /**< ecma_bigint_parse_string_options_t option bits */
{
  ecma_bigint_digit_t radix = 10;
  uint32_t sign = (options & ECMA_BIGINT_PARSE_SET_NEGATIVE) ? ECMA_BIGINT_SIGN : 0;
  bool allow_underscore = options & ECMA_BIGINT_PARSE_ALLOW_UNDERSCORE;

  const lit_utf8_byte_t *string_end_p = string_p + size;
  string_p = ecma_string_trim_front (string_p, string_p + size);
  size = (lit_utf8_size_t) (string_end_p - string_p);

  if (size >= 3 && string_p[0] == LIT_CHAR_0)
  {
    if (string_p[1] == LIT_CHAR_LOWERCASE_X || string_p[1] == LIT_CHAR_UPPERCASE_X)
    {
      radix = 16;
      string_p += 2;
      size -= 2;
    }
    else if (string_p[1] == LIT_CHAR_LOWERCASE_O || string_p[1] == LIT_CHAR_UPPERCASE_O)
    {
      radix = 8;
      string_p += 2;
      size -= 2;
    }
    else if (string_p[1] == LIT_CHAR_LOWERCASE_B || string_p[1] == LIT_CHAR_UPPERCASE_B)
    {
      radix = 2;
      string_p += 2;
      size -= 2;
    }
  }
  else if (size >= 2)
  {
    if (string_p[0] == LIT_CHAR_PLUS)
    {
      size--;
      string_p++;
    }
    else if (string_p[0] == LIT_CHAR_MINUS)
    {
      sign = ECMA_BIGINT_SIGN;
      size--;
      string_p++;
    }
  }
  else if (size == 0)
  {
    return ECMA_BIGINT_ZERO;
  }

  while (string_p < string_end_p && (*string_p == LIT_CHAR_0 || (*string_p == LIT_CHAR_UNDERSCORE && allow_underscore)))
  {
    string_p++;
  }

  ecma_extended_primitive_t *result_p = NULL;

  if (string_p == string_end_p)
  {
    return ECMA_BIGINT_ZERO;
  }

  do
  {
    ecma_bigint_digit_t digit = radix;

    if (*string_p >= LIT_CHAR_0 && *string_p <= LIT_CHAR_9)
    {
      digit = (ecma_bigint_digit_t) (*string_p - LIT_CHAR_0);
    }
    else if (*string_p == LIT_CHAR_UNDERSCORE && allow_underscore)
    {
      continue;
    }
    else
    {
      lit_utf8_byte_t character = (lit_utf8_byte_t) LEXER_TO_ASCII_LOWERCASE (*string_p);

      if (character >= LIT_CHAR_LOWERCASE_A && character <= LIT_CHAR_LOWERCASE_F)
      {
        digit = (ecma_bigint_digit_t) (character - (LIT_CHAR_LOWERCASE_A - 10));
      }
      else if (ecma_string_trim_front (string_p, string_end_p) == string_end_p)
      {
        string_p = string_end_p;
        break;
      }
    }
    if (digit >= radix)
    {
      if (result_p != NULL)
      {
        ecma_deref_bigint (result_p);
      }

      if (options & ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR)
      {
        return ECMA_VALUE_FALSE;
      }
      return ecma_raise_syntax_error (ECMA_ERR_MSG ("String cannot be converted to BigInt value"));
    }

    result_p = ecma_big_uint_mul_digit (result_p, radix, digit);

    if (JERRY_UNLIKELY (result_p == NULL))
    {
      break;
    }
  }
  while (++string_p < string_end_p);

  if (JERRY_UNLIKELY (result_p == NULL))
  {
    if (options & ECMA_BIGINT_PARSE_DISALLOW_MEMORY_ERROR)
    {
      return ECMA_VALUE_NULL;
    }
    return ecma_bigint_raise_memory_error ();
  }

  result_p->u.bigint_sign_and_size |= sign;
  return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
} /* ecma_bigint_parse_string */
ecma_bigint_parse_string (const lit_utf8_byte_t *string_p,  
                          lit_utf8_size_t size,  
                          uint32_t options)  
{
  ecma_bigint_digit_t radix = 10;
  uint32_t sign = (options & ECMA_BIGINT_PARSE_SET_NEGATIVE) ? ECMA_BIGINT_SIGN : 0;
  bool allow_underscore = options & ECMA_BIGINT_PARSE_ALLOW_UNDERSCORE;

  const lit_utf8_byte_t *string_end_p = string_p + size;
  string_p = ecma_string_trim_front (string_p, string_p + size);
  size = (lit_utf8_size_t) (string_end_p - string_p);

  if (size >= 3 && string_p[0] == LIT_CHAR_0)
  {
    if (string_p[1] == LIT_CHAR_LOWERCASE_X || string_p[1] == LIT_CHAR_UPPERCASE_X)
    {
      radix = 16;
      string_p += 2;
      size -= 2;
    }
    else if (string_p[1] == LIT_CHAR_LOWERCASE_O || string_p[1] == LIT_CHAR_UPPERCASE_O)
    {
      radix = 8;
      string_p += 2;
      size -= 2;
    }
    else if (string_p[1] == LIT_CHAR_LOWERCASE_B || string_p[1] == LIT_CHAR_UPPERCASE_B)
    {
      radix = 2;
      string_p += 2;
      size -= 2;
    }
  }
  else if (size >= 2)
  {
    if (string_p[0] == LIT_CHAR_PLUS)
    {
      size--;
      string_p++;
    }
    else if (string_p[0] == LIT_CHAR_MINUS)
    {
      sign = ECMA_BIGINT_SIGN;
      size--;
      string_p++;
    }
  }
  else if (size == 0)
  {
    return ECMA_BIGINT_ZERO;
  }

  while (string_p < string_end_p && (*string_p == LIT_CHAR_0 || (*string_p == LIT_CHAR_UNDERSCORE && allow_underscore)))
  {
    string_p++;
  }

  ecma_extended_primitive_t *result_p = NULL;

  if (string_p == string_end_p)
  {
    return ECMA_BIGINT_ZERO;
  }

  do
  {
    ecma_bigint_digit_t digit = radix;

    if (*string_p >= LIT_CHAR_0 && *string_p <= LIT_CHAR_9)
    {
      digit = (ecma_bigint_digit_t) (*string_p - LIT_CHAR_0);
    }
    else if (*string_p == LIT_CHAR_UNDERSCORE && allow_underscore)
    {
      continue;
    }
    else
    {
      lit_utf8_byte_t character = (lit_utf8_byte_t) LEXER_TO_ASCII_LOWERCASE (*string_p);

      if (character >= LIT_CHAR_LOWERCASE_A && character <= LIT_CHAR_LOWERCASE_F)
      {
        digit = (ecma_bigint_digit_t) (character - (LIT_CHAR_LOWERCASE_A - 10));
      }
      else if (ecma_string_trim_front (string_p, string_end_p) == string_end_p)
      {
        string_p = string_end_p;
        break;
      }
    }
    if (digit >= radix)
    {
      if (result_p != NULL)
      {
        ecma_deref_bigint (result_p);
      }

      if (options & ECMA_BIGINT_PARSE_DISALLOW_SYNTAX_ERROR)
      {
        return ECMA_VALUE_FALSE;
      }
      return ecma_raise_syntax_error (ECMA_ERR_MSG ("String cannot be converted to BigInt value"));
    }

    result_p = ecma_big_uint_mul_digit (result_p, radix, digit);

    if (JERRY_UNLIKELY (result_p == NULL))
    {
      break;
    }
  }
  while (++string_p < string_end_p);

  if (JERRY_UNLIKELY (result_p == NULL))
  {
    if (options & ECMA_BIGINT_PARSE_DISALLOW_MEMORY_ERROR)
    {
      return ECMA_VALUE_NULL;
    }
    return ecma_bigint_raise_memory_error ();
  }

  result_p->u.bigint_sign_and_size |= sign;
  return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
}  