OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "core/svg/SVGParsingError.h" |
| 6 |
| 7 #include "core/dom/QualifiedName.h" |
| 8 #include "platform/JSONValues.h" |
| 9 #include "wtf/text/CharacterNames.h" |
| 10 #include "wtf/text/StringBuilder.h" |
| 11 |
| 12 #include <utility> |
| 13 |
| 14 namespace blink { |
| 15 |
| 16 namespace { |
| 17 |
| 18 void appendErrorContextInfo(StringBuilder& builder, const String& tagName, const
QualifiedName& name) |
| 19 { |
| 20 builder.append('<'); |
| 21 builder.append(tagName); |
| 22 builder.appendLiteral("> attribute "); |
| 23 builder.append(name.toString()); |
| 24 } |
| 25 |
| 26 std::pair<const char*, const char*> messageForStatus(SVGParseStatus status) |
| 27 { |
| 28 switch (status) { |
| 29 case SVGParseStatus::TrailingGarbage: |
| 30 return std::make_pair("Trailing garbage, ", "."); |
| 31 case SVGParseStatus::ExpectedBoolean: |
| 32 return std::make_pair("Expected 'true' or 'false', ", "."); |
| 33 case SVGParseStatus::ExpectedEnumeration: |
| 34 return std::make_pair("Unrecognized enumerated value, ", "."); |
| 35 case SVGParseStatus::NegativeValue: |
| 36 return std::make_pair("A negative value is not valid. (", ")"); |
| 37 case SVGParseStatus::ParsingFailed: |
| 38 default: |
| 39 ASSERT_NOT_REACHED(); |
| 40 break; |
| 41 } |
| 42 return std::make_pair("", ""); |
| 43 } |
| 44 |
| 45 bool disableLocus(SVGParseStatus status) |
| 46 { |
| 47 // Disable locus for semantic errors and generic errors (see TODO below). |
| 48 return status == SVGParseStatus::NegativeValue |
| 49 || status == SVGParseStatus::ParsingFailed; |
| 50 } |
| 51 |
| 52 void appendValue(StringBuilder& builder, SVGParsingError error, const AtomicStri
ng& value) |
| 53 { |
| 54 builder.append('"'); |
| 55 if (!error.hasLocus() || disableLocus(error.status())) { |
| 56 escapeStringForJSON(value.string(), &builder); |
| 57 } else { |
| 58 // Emit a string on the form: '"[...]<before><after>[...]"' |
| 59 unsigned locus = error.locus(); |
| 60 ASSERT(locus <= value.length()); |
| 61 |
| 62 // Amount of context to show before/after the error. |
| 63 const unsigned kContext = 16; |
| 64 |
| 65 unsigned contextStart = std::max(locus, kContext) - kContext; |
| 66 unsigned contextEnd = std::min(locus + kContext, value.length()); |
| 67 ASSERT(contextStart <= contextEnd); |
| 68 ASSERT(contextEnd <= value.length()); |
| 69 if (contextStart != 0) |
| 70 builder.append(horizontalEllipsisCharacter); |
| 71 escapeStringForJSON(value.string().substring(contextStart, contextEnd -
contextStart), &builder); |
| 72 if (contextEnd != value.length()) |
| 73 builder.append(horizontalEllipsisCharacter); |
| 74 } |
| 75 builder.append('"'); |
| 76 } |
| 77 |
| 78 } |
| 79 |
| 80 String SVGParsingError::format(const String& tagName, const QualifiedName& name,
const AtomicString& value) const |
| 81 { |
| 82 StringBuilder builder; |
| 83 |
| 84 // TODO(fs): Remove this case once enough specific errors have been added. |
| 85 if (status() == SVGParseStatus::ParsingFailed) { |
| 86 builder.appendLiteral("Invalid value for "); |
| 87 appendErrorContextInfo(builder, tagName, name); |
| 88 builder.append('='); |
| 89 appendValue(builder, *this, value); |
| 90 } else { |
| 91 appendErrorContextInfo(builder, tagName, name); |
| 92 builder.appendLiteral(": "); |
| 93 |
| 94 if (hasLocus() && locus() == value.length()) |
| 95 builder.appendLiteral("Unexpected end of attribute. "); |
| 96 |
| 97 auto message = messageForStatus(status()); |
| 98 builder.append(message.first); |
| 99 appendValue(builder, *this, value); |
| 100 builder.append(message.second); |
| 101 } |
| 102 return builder.toString(); |
| 103 } |
| 104 |
| 105 } // namespace blink |
OLD | NEW |