Exemple #1
0
nsresult
SVGPointList::SetValueFromString(const nsAString& aValue)
{
  // The spec says that the list is parsed and accepted up to the first error
  // encountered, so we must call CopyFrom even if an error occurs. We still
  // want to throw any error code from setAttribute if there's a problem
  // though, so we must take care to return any error code.

  nsresult rv = NS_OK;

  SVGPointList temp;

  nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
    tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);

  while (tokenizer.hasMoreTokens()) {

    const nsAString& token = tokenizer.nextToken();

    RangedPtr<const PRUnichar> iter =
      SVGContentUtils::GetStartRangedPtr(token);
    const RangedPtr<const PRUnichar> end =
      SVGContentUtils::GetEndRangedPtr(token);

    float x;
    if (!SVGContentUtils::ParseNumber(iter, end, x)) {
      rv = NS_ERROR_DOM_SYNTAX_ERR;
      break;
    }

    float y;
    if (iter == end) {
      if (!tokenizer.hasMoreTokens() ||
          !SVGContentUtils::ParseNumber(tokenizer.nextToken(), y)) {
        rv = NS_ERROR_DOM_SYNTAX_ERR;
        break;
      }
    } else {
      // It's possible for the token to be 10-30 which has
      // no separator but needs to be parsed as 10, -30
      const nsAString& leftOver = Substring(iter.get(), end.get());
      if (leftOver[0] != '-' || !SVGContentUtils::ParseNumber(leftOver, y)) {
        rv = NS_ERROR_DOM_SYNTAX_ERR;
        break;
      }
    }
    temp.AppendItem(SVGPoint(x, y));
  }
  if (tokenizer.separatorAfterCurrentToken()) {
    rv = NS_ERROR_DOM_SYNTAX_ERR; // trailing comma
  }
  nsresult rv2 = CopyFrom(temp);
  if (NS_FAILED(rv2)) {
    return rv2; // prioritize OOM error code over syntax errors
  }
  return rv;
}
Exemple #2
0
bool
js::IndexToIdSlow(ExclusiveContext *cx, uint32_t index, MutableHandleId idp)
{
    MOZ_ASSERT(index > JSID_INT_MAX);

    char16_t buf[UINT32_CHAR_BUFFER_LENGTH];
    RangedPtr<char16_t> end(ArrayEnd(buf), buf, ArrayEnd(buf));
    RangedPtr<char16_t> start = BackfillIndexInCharBuffer(index, end);

    JSAtom *atom = AtomizeChars(cx, start.get(), end - start);
    if (!atom)
        return false;

    idp.set(JSID_FROM_BITS((size_t)atom));
    return true;
}
Exemple #3
0
bool
js::IndexToIdSlow(JSContext *cx, uint32_t index,
                  typename MaybeRooted<jsid, allowGC>::MutableHandleType idp)
{
    JS_ASSERT(index > JSID_INT_MAX);

    jschar buf[UINT32_CHAR_BUFFER_LENGTH];
    RangedPtr<jschar> end(ArrayEnd(buf), buf, ArrayEnd(buf));
    RangedPtr<jschar> start = BackfillIndexInCharBuffer(index, end);

    JSAtom *atom = AtomizeChars<allowGC>(cx, start.get(), end - start);
    if (!atom)
        return false;

    idp.set(JSID_FROM_BITS((size_t)atom));
    return true;
}
static bool
GetValueFromString(const nsAString& aString,
                   float& aValue,
                   uint16_t* aUnitType)
{
  RangedPtr<const char16_t> iter =
    SVGContentUtils::GetStartRangedPtr(aString);
  const RangedPtr<const char16_t> end =
    SVGContentUtils::GetEndRangedPtr(aString);

  if (!SVGContentUtils::ParseNumber(iter, end, aValue)) {
    return false;
  }
  const nsAString& units = Substring(iter.get(), end.get());
  *aUnitType = GetUnitTypeForString(units);
  return IsValidUnitType(*aUnitType);
}
Exemple #5
0
bool
IndexToIdSlow(JSContext *cx, uint32 index, jsid *idp)
{
    JS_ASSERT(index > JSID_INT_MAX);

    jschar buf[UINT32_CHAR_BUFFER_LENGTH];
    RangedPtr<jschar> end(buf + JS_ARRAY_LENGTH(buf), buf, buf + JS_ARRAY_LENGTH(buf));
    RangedPtr<jschar> start = BackfillIndexInCharBuffer(index, end);

    JSAtom *atom = js_AtomizeChars(cx, start.get(), end - start);
    if (!atom)
        return false;

    *idp = ATOM_TO_JSID(atom);
    JS_ASSERT(js_CheckForStringIndex(*idp) == *idp);
    return true;
}
Exemple #6
0
bool
SVGLength::SetValueFromString(const nsAString &aString)
{
  RangedPtr<const char16_t> iter =
    SVGContentUtils::GetStartRangedPtr(aString);
  const RangedPtr<const char16_t> end =
    SVGContentUtils::GetEndRangedPtr(aString);

  float value;

  if (!SVGContentUtils::ParseNumber(iter, end, value)) {
    return false;
  }

  const nsAString& units = Substring(iter.get(), end.get());
  uint16_t unitType = GetUnitTypeForString(units);
  if (!IsValidUnitType(unitType)) {
    return false;
  }
  mValue = value;
  mUnit = uint8_t(unitType);
  return true;
}
Exemple #7
0
static bool
GetValueFromString(const nsAString& aString,
                   bool aPercentagesAllowed,
                   float& aValue)
{
  RangedPtr<const char16_t> iter =
    SVGContentUtils::GetStartRangedPtr(aString);
  const RangedPtr<const char16_t> end =
    SVGContentUtils::GetEndRangedPtr(aString);

  if (!SVGContentUtils::ParseNumber(iter, end, aValue)) {
    return false;
  }

  if (aPercentagesAllowed) {
    const nsAString& units = Substring(iter.get(), end.get());
    if (units.EqualsLiteral("%")) {
      aValue /= 100;
      return true;
    }
  }

  return iter == end;
}
Exemple #8
0
JSONParser::Token
JSONParser::readNumber()
{
    JS_ASSERT(current < end);
    JS_ASSERT(JS7_ISDEC(*current) || *current == '-');

    /*
     * JSONNumber:
     *   /^-?(0|[1-9][0-9]+)(\.[0-9]+)?([eE][\+\-]?[0-9]+)?$/
     */

    bool negative = *current == '-';

    /* -? */
    if (negative && ++current == end) {
        error("no number after minus sign");
        return token(Error);
    }

    const RangedPtr<const jschar> digitStart = current;

    /* 0|[1-9][0-9]+ */
    if (!JS7_ISDEC(*current)) {
        error("unexpected non-digit");
        return token(Error);
    }
    if (*current++ != '0') {
        for (; current < end; current++) {
            if (!JS7_ISDEC(*current))
                break;
        }
    }

    /* Fast path: no fractional or exponent part. */
    if (current == end || (*current != '.' && *current != 'e' && *current != 'E')) {
        TwoByteChars chars(digitStart.get(), current - digitStart);
        if (chars.length() < strlen("9007199254740992")) {
            // If the decimal number is shorter than the length of 2**53, (the
            // largest number a double can represent with integral precision),
            // parse it using a decimal-only parser.  This comparison is
            // conservative but faster than a fully-precise check.
            double d = ParseDecimalNumber(chars);
            return numberToken(negative ? -d : d);
        }

        double d;
        const jschar *dummy;
        if (!GetPrefixInteger(cx, digitStart.get(), current.get(), 10, &dummy, &d))
            return token(OOM);
        JS_ASSERT(current == dummy);
        return numberToken(negative ? -d : d);
    }

    /* (\.[0-9]+)? */
    if (current < end && *current == '.') {
        if (++current == end) {
            error("missing digits after decimal point");
            return token(Error);
        }
        if (!JS7_ISDEC(*current)) {
            error("unterminated fractional number");
            return token(Error);
        }
        while (++current < end) {
            if (!JS7_ISDEC(*current))
                break;
        }
    }

    /* ([eE][\+\-]?[0-9]+)? */
    if (current < end && (*current == 'e' || *current == 'E')) {
        if (++current == end) {
            error("missing digits after exponent indicator");
            return token(Error);
        }
        if (*current == '+' || *current == '-') {
            if (++current == end) {
                error("missing digits after exponent sign");
                return token(Error);
            }
        }
        if (!JS7_ISDEC(*current)) {
            error("exponent part is missing a number");
            return token(Error);
        }
        while (++current < end) {
            if (!JS7_ISDEC(*current))
                break;
        }
    }

    double d;
    const jschar *finish;
    if (!js_strtod(cx, digitStart.get(), current.get(), &finish, &d))
        return token(OOM);
    JS_ASSERT(current == finish);
    return numberToken(negative ? -d : d);
}
Exemple #9
0
JSONParser::Token
JSONParser::readString()
{
    JS_ASSERT(current < end);
    JS_ASSERT(*current == '"');

    /*
     * JSONString:
     *   /^"([^\u0000-\u001F"\\]|\\(["/\\bfnrt]|u[0-9a-fA-F]{4}))*"$/
     */

    if (++current == end) {
        error("unterminated string literal");
        return token(Error);
    }

    /*
     * Optimization: if the source contains no escaped characters, create the
     * string directly from the source text.
     */
    RangedPtr<const jschar> start = current;
    for (; current < end; current++) {
        if (*current == '"') {
            size_t length = current - start;
            current++;
            JSFlatString *str = (ST == JSONParser::PropertyName)
                                ? AtomizeChars(cx, start.get(), length)
                                : js_NewStringCopyN<CanGC>(cx, start.get(), length);
            if (!str)
                return token(OOM);
            return stringToken(str);
        }

        if (*current == '\\')
            break;

        if (*current <= 0x001F) {
            error("bad control character in string literal");
            return token(Error);
        }
    }

    /*
     * Slow case: string contains escaped characters.  Copy a maximal sequence
     * of unescaped characters into a temporary buffer, then an escaped
     * character, and repeat until the entire string is consumed.
     */
    StringBuffer buffer(cx);
    do {
        if (start < current && !buffer.append(start.get(), current.get()))
            return token(OOM);

        if (current >= end)
            break;

        jschar c = *current++;
        if (c == '"') {
            JSFlatString *str = (ST == JSONParser::PropertyName)
                                ? buffer.finishAtom()
                                : buffer.finishString();
            if (!str)
                return token(OOM);
            return stringToken(str);
        }

        if (c != '\\') {
            --current;
            error("bad character in string literal");
            return token(Error);
        }

        if (current >= end)
            break;

        switch (*current++) {
          case '"':  c = '"';  break;
          case '/':  c = '/';  break;
          case '\\': c = '\\'; break;
          case 'b':  c = '\b'; break;
          case 'f':  c = '\f'; break;
          case 'n':  c = '\n'; break;
          case 'r':  c = '\r'; break;
          case 't':  c = '\t'; break;

          case 'u':
            if (end - current < 4 ||
                !(JS7_ISHEX(current[0]) &&
                  JS7_ISHEX(current[1]) &&
                  JS7_ISHEX(current[2]) &&
                  JS7_ISHEX(current[3])))
            {
                // Point to the first non-hexadecimal character (which may be
                // missing).
                if (current == end || !JS7_ISHEX(current[0]))
                    ; // already at correct location
                else if (current + 1 == end || !JS7_ISHEX(current[1]))
                    current += 1;
                else if (current + 2 == end || !JS7_ISHEX(current[2]))
                    current += 2;
                else if (current + 3 == end || !JS7_ISHEX(current[3]))
                    current += 3;
                else
                    MOZ_ASSUME_UNREACHABLE("logic error determining first erroneous character");

                error("bad Unicode escape");
                return token(Error);
            }
            c = (JS7_UNHEX(current[0]) << 12)
              | (JS7_UNHEX(current[1]) << 8)
              | (JS7_UNHEX(current[2]) << 4)
              | (JS7_UNHEX(current[3]));
            current += 4;
            break;

          default:
            current--;
            error("bad escaped character");
            return token(Error);
        }
        if (!buffer.append(c))
            return token(OOM);

        start = current;
        for (; current < end; current++) {
            if (*current == '"' || *current == '\\' || *current <= 0x001F)
                break;
        }
    } while (current < end);

    error("unterminated string");
    return token(Error);
}
Exemple #10
0
JSONParser::Token
JSONParser::readString()
{
    JS_ASSERT(current < end);
    JS_ASSERT(*current == '"');

    /*
     * JSONString:
     *   /^"([^\u0000-\u001F"\\]|\\(["/\\bfnrt]|u[0-9a-fA-F]{4}))*"$/
     */

    if (++current == end) {
        error("unterminated string literal");
        return token(Error);
    }

    /*
     * Optimization: if the source contains no escaped characters, create the
     * string directly from the source text.
     */
    RangedPtr<const jschar> start = current;
    for (; current < end; current++) {
        if (*current == '"') {
            size_t length = current - start;
            current++;
            JSFlatString *str = (ST == JSONParser::PropertyName)
                                ? AtomizeChars(cx, start.get(), length)
                                : js_NewStringCopyN(cx, start.get(), length);
            if (!str)
                return token(OOM);
            return stringToken(str);
        }

        if (*current == '\\')
            break;

        if (*current <= 0x001F) {
            error("bad control character in string literal");
            return token(Error);
        }
    }

    /*
     * Slow case: string contains escaped characters.  Copy a maximal sequence
     * of unescaped characters into a temporary buffer, then an escaped
     * character, and repeat until the entire string is consumed.
     */
    StringBuffer buffer(cx);
    do {
        if (start < current && !buffer.append(start.get(), current.get()))
            return token(OOM);

        if (current >= end)
            break;

        jschar c = *current++;
        if (c == '"') {
            UnrootedFlatString str = (ST == JSONParser::PropertyName)
                                     ? UnrootedFlatString(buffer.finishAtom())
                                     : buffer.finishString();
            if (!str)
                return token(OOM);
            return stringToken(str);
        }

        if (c != '\\') {
            error("bad character in string literal");
            return token(Error);
        }

        if (current >= end)
            break;

        switch (*current++) {
        case '"':
            c = '"';
            break;
        case '/':
            c = '/';
            break;
        case '\\':
            c = '\\';
            break;
        case 'b':
            c = '\b';
            break;
        case 'f':
            c = '\f';
            break;
        case 'n':
            c = '\n';
            break;
        case 'r':
            c = '\r';
            break;
        case 't':
            c = '\t';
            break;

        case 'u':
            if (end - current < 4) {
                error("bad Unicode escape");
                return token(Error);
            }
            if (JS7_ISHEX(current[0]) &&
                    JS7_ISHEX(current[1]) &&
                    JS7_ISHEX(current[2]) &&
                    JS7_ISHEX(current[3]))
            {
                c = (JS7_UNHEX(current[0]) << 12)
                    | (JS7_UNHEX(current[1]) << 8)
                    | (JS7_UNHEX(current[2]) << 4)
                    | (JS7_UNHEX(current[3]));
                current += 4;
                break;
            }
        /* FALL THROUGH */

        default:
            error("bad escaped character");
            return token(Error);
        }
        if (!buffer.append(c))
            return token(OOM);

        start = current;
        for (; current < end; current++) {
            if (*current == '"' || *current == '\\' || *current <= 0x001F)
                break;
        }
    } while (current < end);

    error("unterminated string");
    return token(Error);
}
Exemple #11
0
JSONParser::Token
JSONParser::readNumber()
{
    JS_ASSERT(current < end);
    JS_ASSERT(JS7_ISDEC(*current) || *current == '-');

    /*
     * JSONNumber:
     *   /^-?(0|[1-9][0-9]+)(\.[0-9]+)?([eE][\+\-]?[0-9]+)?$/
     */

    bool negative = *current == '-';

    /* -? */
    if (negative && ++current == end) {
        error("no number after minus sign");
        return token(Error);
    }

    const RangedPtr<const jschar> digitStart = current;

    /* 0|[1-9][0-9]+ */
    if (!JS7_ISDEC(*current)) {
        error("unexpected non-digit");
        return token(Error);
    }
    if (*current++ != '0') {
        for (; current < end; current++) {
            if (!JS7_ISDEC(*current))
                break;
        }
    }

    /* Fast path: no fractional or exponent part. */
    if (current == end || (*current != '.' && *current != 'e' && *current != 'E')) {
        const jschar *dummy;
        double d;
        if (!GetPrefixInteger(cx, digitStart.get(), current.get(), 10, &dummy, &d))
            return token(OOM);
        JS_ASSERT(current == dummy);
        return numberToken(negative ? -d : d);
    }

    /* (\.[0-9]+)? */
    if (current < end && *current == '.') {
        if (++current == end) {
            error("missing digits after decimal point");
            return token(Error);
        }
        if (!JS7_ISDEC(*current)) {
            error("unterminated fractional number");
            return token(Error);
        }
        while (++current < end) {
            if (!JS7_ISDEC(*current))
                break;
        }
    }

    /* ([eE][\+\-]?[0-9]+)? */
    if (current < end && (*current == 'e' || *current == 'E')) {
        if (++current == end) {
            error("missing digits after exponent indicator");
            return token(Error);
        }
        if (*current == '+' || *current == '-') {
            if (++current == end) {
                error("missing digits after exponent sign");
                return token(Error);
            }
        }
        if (!JS7_ISDEC(*current)) {
            error("exponent part is missing a number");
            return token(Error);
        }
        while (++current < end) {
            if (!JS7_ISDEC(*current))
                break;
        }
    }

    double d;
    const jschar *finish;
    if (!js_strtod(cx, digitStart.get(), current.get(), &finish, &d))
        return token(OOM);
    JS_ASSERT(current == finish);
    return numberToken(negative ? -d : d);
}