SVGPointList.cpp (3019B)
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 "SVGPointList.h" 8 9 #include "SVGContentUtils.h" 10 #include "nsCharSeparatedTokenizer.h" 11 #include "nsContentUtils.h" 12 #include "nsTextFormatter.h" 13 14 namespace mozilla { 15 16 nsresult SVGPointList::CopyFrom(const SVGPointList& rhs) { 17 if (!mItems.Assign(rhs.mItems, fallible)) { 18 return NS_ERROR_OUT_OF_MEMORY; 19 } 20 return NS_OK; 21 } 22 23 void SVGPointList::GetValueAsString(nsAString& aValue) const { 24 aValue.Truncate(); 25 char16_t buf[50]; 26 uint32_t last = mItems.Length() - 1; 27 for (uint32_t i = 0; i < mItems.Length(); ++i) { 28 // Would like to use aValue.AppendPrintf("%f,%f", item.mX, item.mY), 29 // but it's not possible to always avoid trailing zeros. 30 nsTextFormatter::snprintf(buf, std::size(buf), u"%g,%g", 31 double(mItems[i].mX), double(mItems[i].mY)); 32 // We ignore OOM, since it's not useful for us to return an error. 33 aValue.Append(buf); 34 if (i != last) { 35 aValue.Append(' '); 36 } 37 } 38 } 39 40 nsresult SVGPointList::SetValueFromString(const nsAString& aValue) { 41 // The spec says that the list is parsed and accepted up to the first error 42 // encountered, so we must call CopyFrom even if an error occurs. We still 43 // want to throw any error code from setAttribute if there's a problem 44 // though, so we must take care to return any error code. 45 46 nsresult rv = NS_OK; 47 48 SVGPointList temp; 49 50 nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace, 51 nsTokenizerFlags::SeparatorOptional> 52 tokenizer(aValue, ','); 53 54 while (tokenizer.hasMoreTokens()) { 55 const nsAString& token = tokenizer.nextToken(); 56 57 nsAString::const_iterator iter, end; 58 token.BeginReading(iter); 59 token.EndReading(end); 60 61 float x; 62 if (!SVGContentUtils::ParseNumber(iter, end, x)) { 63 rv = NS_ERROR_DOM_SYNTAX_ERR; 64 break; 65 } 66 67 float y; 68 if (iter == end) { 69 if (!tokenizer.hasMoreTokens() || 70 !SVGContentUtils::ParseNumber(tokenizer.nextToken(), y)) { 71 rv = NS_ERROR_DOM_SYNTAX_ERR; 72 break; 73 } 74 } else { 75 // It's possible for the token to be 10-30 which has 76 // no separator but needs to be parsed as 10, -30 77 const nsAString& leftOver = Substring(iter, end); 78 if (leftOver[0] != '-' || !SVGContentUtils::ParseNumber(leftOver, y)) { 79 rv = NS_ERROR_DOM_SYNTAX_ERR; 80 break; 81 } 82 } 83 temp.AppendItem(SVGPoint(x, y)); 84 } 85 if (tokenizer.separatorAfterCurrentToken()) { 86 rv = NS_ERROR_DOM_SYNTAX_ERR; // trailing comma 87 } 88 nsresult rv2 = CopyFrom(temp); 89 if (NS_FAILED(rv2)) { 90 return rv2; // prioritize OOM error code over syntax errors 91 } 92 return rv; 93 } 94 95 } // namespace mozilla