Chromium Code Reviews| Index: third_party/WebKit/Source/core/svg/SVGParsingError.cpp |
| diff --git a/third_party/WebKit/Source/core/svg/SVGParsingError.cpp b/third_party/WebKit/Source/core/svg/SVGParsingError.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..cb072e1b2ebeff1d430dd8ed36b544e9e544c063 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/svg/SVGParsingError.cpp |
| @@ -0,0 +1,103 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "core/svg/SVGParsingError.h" |
| + |
| +#include "core/dom/QualifiedName.h" |
| +#include "platform/JSONValues.h" |
| +#include "wtf/text/CharacterNames.h" |
| +#include "wtf/text/StringBuilder.h" |
| + |
| +#include <utility> |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +void appendErrorContextInfo(StringBuilder& builder, const String& tagName, const QualifiedName& name) |
| +{ |
| + builder.append('<'); |
| + builder.append(tagName); |
| + builder.appendLiteral("> attribute "); |
| + builder.append(name.toString()); |
| +} |
| + |
| +std::pair<const char*, const char*> messageForStatus(SVGStatus status) |
| +{ |
| + switch (status) { |
| + case SVGStatus::TrailingGarbage: |
| + return std::make_pair("Trailing garbage, ", "."); |
| + case SVGStatus::ExpectedBoolean: |
| + return std::make_pair("Expected 'true' or 'false', ", "."); |
| + case SVGStatus::ExpectedEnumeration: |
| + return std::make_pair("Unrecognized enumerated value, ", "."); |
| + case SVGStatus::NegativeValue: |
| + return std::make_pair("A negative value is not valid. (", ")"); |
| + case SVGStatus::ParsingFailed: |
| + default: |
| + ASSERT_NOT_REACHED(); |
| + break; |
| + } |
| + return std::make_pair("", ""); |
| +} |
| + |
| +bool disableLocus(SVGStatus status) |
| +{ |
| + // Disable locus for semantic errors and generic errors (see TODO below). |
| + return status == SVGStatus::NegativeValue |
| + || status == SVGStatus::ParsingFailed; |
| +} |
| + |
| +void appendValue(StringBuilder& builder, SVGParsingError error, const AtomicString& value) |
| +{ |
| + builder.append('"'); |
| + if (!error.hasLocus() || disableLocus(error.status())) { |
| + escapeStringForJSON(value.string(), &builder); |
| + } else { |
| + // Emit a string on the form: '"[...]<before><after>[...]"' |
| + unsigned locus = error.locus(); |
| + ASSERT(locus >= 0 && locus <= value.length()); |
|
f(malita)
2016/01/15 20:03:38
nit: first part is obvious for unsigned.
fs
2016/01/15 20:46:14
Indeed, will fix.
fs
2016/01/18 13:56:51
Done.
|
| + |
| + // Amount of context to show before/after the error. |
| + const unsigned kContext = 16; |
| + |
| + unsigned contextStart = std::max(locus, kContext) - kContext; |
| + unsigned contextEnd = std::min(locus + kContext, value.length()); |
|
f(malita)
2016/01/15 20:03:38
nit: I think these are safe, but just for sanity,
fs
2016/01/15 20:46:14
String::substring is pretty resilient to weird ran
fs
2016/01/18 13:56:51
Added.
|
| + if (contextStart != 0) |
| + builder.append(horizontalEllipsisCharacter); |
| + escapeStringForJSON(value.string().substring(contextStart, contextEnd - contextStart), &builder); |
|
f(malita)
2016/01/15 20:03:38
So the parse error is somewhere within this (poten
fs
2016/01/15 20:46:14
Yeah, initially I had this displaying a caret usin
|
| + if (contextEnd != value.length()) |
| + builder.append(horizontalEllipsisCharacter); |
| + } |
| + builder.append('"'); |
| +} |
| + |
| +} |
| + |
| +String SVGParsingError::format(const String& tagName, const QualifiedName& name, const AtomicString& value) const |
| +{ |
| + StringBuilder builder; |
| + |
| + // TODO(fs): Remove this case once enough specific errors have been added. |
| + if (status() == SVGStatus::ParsingFailed) { |
| + builder.appendLiteral("Invalid value for "); |
| + appendErrorContextInfo(builder, tagName, name); |
| + builder.append('='); |
| + appendValue(builder, *this, value); |
| + } else { |
| + appendErrorContextInfo(builder, tagName, name); |
| + builder.appendLiteral(": "); |
| + |
| + if (hasLocus() && locus() == value.length()) |
| + builder.appendLiteral("Unexpected end of attribute. "); |
| + |
| + auto message = messageForStatus(status()); |
| + builder.append(message.first); |
| + appendValue(builder, *this, value); |
| + builder.append(message.second); |
| + } |
| + return builder.toString(); |
| +} |
| + |
| +} // namespace blink |