DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (b6d82b1a6b02)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/ArrayUtils.h"

#include "SVGPointList.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsTextFormatter.h"
#include "SVGContentUtils.h"

namespace mozilla {

nsresult SVGPointList::CopyFrom(const SVGPointList& rhs) {
  if (!mItems.Assign(rhs.mItems, fallible)) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  return NS_OK;
}

void SVGPointList::GetValueAsString(nsAString& aValue) const {
  aValue.Truncate();
  char16_t buf[50];
  uint32_t last = mItems.Length() - 1;
  for (uint32_t i = 0; i < mItems.Length(); ++i) {
    // Would like to use aValue.AppendPrintf("%f,%f", item.mX, item.mY),
    // but it's not possible to always avoid trailing zeros.
    nsTextFormatter::snprintf(buf, ArrayLength(buf), u"%g,%g",
                              double(mItems[i].mX), double(mItems[i].mY));
    // We ignore OOM, since it's not useful for us to return an error.
    aValue.Append(buf);
    if (i != last) {
      aValue.Append(' ');
    }
  }
}

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<nsContentUtils::IsHTMLWhitespace> tokenizer(
      aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);

  while (tokenizer.hasMoreTokens()) {
    const nsAString& token = tokenizer.nextToken();

    RangedPtr<const char16_t> iter = SVGContentUtils::GetStartRangedPtr(token);
    const RangedPtr<const char16_t> 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;
}

}  // namespace mozilla