Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/svg/SVGPointList.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/ArrayUtils.h"
8
9
#include "SVGPointList.h"
10
#include "nsCharSeparatedTokenizer.h"
11
#include "nsTextFormatter.h"
12
#include "SVGContentUtils.h"
13
14
namespace mozilla {
15
16
nsresult
17
SVGPointList::CopyFrom(const SVGPointList& rhs)
18
0
{
19
0
  if (!mItems.Assign(rhs.mItems, fallible)) {
20
0
    return NS_ERROR_OUT_OF_MEMORY;
21
0
  }
22
0
  return NS_OK;
23
0
}
24
25
void
26
SVGPointList::GetValueAsString(nsAString& aValue) const
27
0
{
28
0
  aValue.Truncate();
29
0
  char16_t buf[50];
30
0
  uint32_t last = mItems.Length() - 1;
31
0
  for (uint32_t i = 0; i < mItems.Length(); ++i) {
32
0
    // Would like to use aValue.AppendPrintf("%f,%f", item.mX, item.mY),
33
0
    // but it's not possible to always avoid trailing zeros.
34
0
    nsTextFormatter::snprintf(buf, ArrayLength(buf),
35
0
                              u"%g,%g",
36
0
                              double(mItems[i].mX), double(mItems[i].mY));
37
0
    // We ignore OOM, since it's not useful for us to return an error.
38
0
    aValue.Append(buf);
39
0
    if (i != last) {
40
0
      aValue.Append(' ');
41
0
    }
42
0
  }
43
0
}
44
45
nsresult
46
SVGPointList::SetValueFromString(const nsAString& aValue)
47
0
{
48
0
  // The spec says that the list is parsed and accepted up to the first error
49
0
  // encountered, so we must call CopyFrom even if an error occurs. We still
50
0
  // want to throw any error code from setAttribute if there's a problem
51
0
  // though, so we must take care to return any error code.
52
0
53
0
  nsresult rv = NS_OK;
54
0
55
0
  SVGPointList temp;
56
0
57
0
  nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
58
0
    tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
59
0
60
0
  while (tokenizer.hasMoreTokens()) {
61
0
62
0
    const nsAString& token = tokenizer.nextToken();
63
0
64
0
    RangedPtr<const char16_t> iter =
65
0
      SVGContentUtils::GetStartRangedPtr(token);
66
0
    const RangedPtr<const char16_t> end =
67
0
      SVGContentUtils::GetEndRangedPtr(token);
68
0
69
0
    float x;
70
0
    if (!SVGContentUtils::ParseNumber(iter, end, x)) {
71
0
      rv = NS_ERROR_DOM_SYNTAX_ERR;
72
0
      break;
73
0
    }
74
0
75
0
    float y;
76
0
    if (iter == end) {
77
0
      if (!tokenizer.hasMoreTokens() ||
78
0
          !SVGContentUtils::ParseNumber(tokenizer.nextToken(), y)) {
79
0
        rv = NS_ERROR_DOM_SYNTAX_ERR;
80
0
        break;
81
0
      }
82
0
    } else {
83
0
      // It's possible for the token to be 10-30 which has
84
0
      // no separator but needs to be parsed as 10, -30
85
0
      const nsAString& leftOver = Substring(iter.get(), end.get());
86
0
      if (leftOver[0] != '-' || !SVGContentUtils::ParseNumber(leftOver, y)) {
87
0
        rv = NS_ERROR_DOM_SYNTAX_ERR;
88
0
        break;
89
0
      }
90
0
    }
91
0
    temp.AppendItem(SVGPoint(x, y));
92
0
  }
93
0
  if (tokenizer.separatorAfterCurrentToken()) {
94
0
    rv = NS_ERROR_DOM_SYNTAX_ERR; // trailing comma
95
0
  }
96
0
  nsresult rv2 = CopyFrom(temp);
97
0
  if (NS_FAILED(rv2)) {
98
0
    return rv2; // prioritize OOM error code over syntax errors
99
0
  }
100
0
  return rv;
101
0
}
102
103
} // namespace mozilla