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(SVGStatus status) | |
27 { | |
28 switch (status) { | |
29 case SVGStatus::TrailingGarbage: | |
30 return std::make_pair("Trailing garbage, ", "."); | |
31 case SVGStatus::ExpectedBoolean: | |
32 return std::make_pair("Expected 'true' or 'false', ", "."); | |
33 case SVGStatus::ExpectedEnumeration: | |
34 return std::make_pair("Unrecognized enumerated value, ", "."); | |
35 case SVGStatus::NegativeValue: | |
36 return std::make_pair("A negative value is not valid. (", ")"); | |
37 case SVGStatus::ParsingFailed: | |
38 default: | |
39 ASSERT_NOT_REACHED(); | |
40 break; | |
41 } | |
42 return std::make_pair("", ""); | |
43 } | |
44 | |
45 bool disableLocus(SVGStatus status) | |
46 { | |
47 // Disable locus for semantic errors and generic errors (see TODO below). | |
48 return status == SVGStatus::NegativeValue | |
49 || status == SVGStatus::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 >= 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.
| |
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()); | |
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.
| |
67 if (contextStart != 0) | |
68 builder.append(horizontalEllipsisCharacter); | |
69 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
| |
70 if (contextEnd != value.length()) | |
71 builder.append(horizontalEllipsisCharacter); | |
72 } | |
73 builder.append('"'); | |
74 } | |
75 | |
76 } | |
77 | |
78 String SVGParsingError::format(const String& tagName, const QualifiedName& name, const AtomicString& value) const | |
79 { | |
80 StringBuilder builder; | |
81 | |
82 // TODO(fs): Remove this case once enough specific errors have been added. | |
83 if (status() == SVGStatus::ParsingFailed) { | |
84 builder.appendLiteral("Invalid value for "); | |
85 appendErrorContextInfo(builder, tagName, name); | |
86 builder.append('='); | |
87 appendValue(builder, *this, value); | |
88 } else { | |
89 appendErrorContextInfo(builder, tagName, name); | |
90 builder.appendLiteral(": "); | |
91 | |
92 if (hasLocus() && locus() == value.length()) | |
93 builder.appendLiteral("Unexpected end of attribute. "); | |
94 | |
95 auto message = messageForStatus(status()); | |
96 builder.append(message.first); | |
97 appendValue(builder, *this, value); | |
98 builder.append(message.second); | |
99 } | |
100 return builder.toString(); | |
101 } | |
102 | |
103 } // namespace blink | |
OLD | NEW |