| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "config.h" | 25 #include "config.h" |
| 26 #include "core/dom/DOMTokenList.h" | 26 #include "core/dom/DOMTokenList.h" |
| 27 | 27 |
| 28 #include "bindings/v8/ExceptionState.h" | 28 #include "bindings/v8/ExceptionState.h" |
| 29 #include "core/dom/ExceptionCode.h" | 29 #include "core/dom/ExceptionCode.h" |
| 30 #include "core/html/parser/HTMLParserIdioms.h" | 30 #include "core/html/parser/HTMLParserIdioms.h" |
| 31 #include "wtf/text/StringBuilder.h" | 31 #include "wtf/text/StringBuilder.h" |
| 32 | 32 |
| 33 namespace WebCore { | 33 namespace WebCore { |
| 34 | 34 |
| 35 bool DOMTokenList::validateToken(const AtomicString& token, ExceptionState& exce
ptionState) | 35 bool DOMTokenList::validateToken(const String& token, ExceptionState& exceptionS
tate) |
| 36 { | 36 { |
| 37 if (token.isEmpty()) { | 37 if (token.isEmpty()) { |
| 38 exceptionState.throwDOMException(SyntaxError, "The token provided must n
ot be empty."); | 38 exceptionState.throwDOMException(SyntaxError, "The token provided must n
ot be empty."); |
| 39 return false; | 39 return false; |
| 40 } | 40 } |
| 41 | 41 |
| 42 unsigned length = token.length(); | 42 unsigned length = token.length(); |
| 43 for (unsigned i = 0; i < length; ++i) { | 43 for (unsigned i = 0; i < length; ++i) { |
| 44 if (isHTMLSpace<UChar>(token[i])) { | 44 if (isHTMLSpace<UChar>(token[i])) { |
| 45 exceptionState.throwDOMException(InvalidCharacterError, "The token p
rovided ('" + token + "') contains HTML space characters, which are not valid in
tokens."); | 45 exceptionState.throwDOMException(InvalidCharacterError, "The token p
rovided ('" + token + "') contains HTML space characters, which are not valid in
tokens."); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 67 return containsInternal(token); | 67 return containsInternal(token); |
| 68 } | 68 } |
| 69 | 69 |
| 70 void DOMTokenList::add(const AtomicString& token, ExceptionState& exceptionState
) | 70 void DOMTokenList::add(const AtomicString& token, ExceptionState& exceptionState
) |
| 71 { | 71 { |
| 72 Vector<String> tokens; | 72 Vector<String> tokens; |
| 73 tokens.append(token.string()); | 73 tokens.append(token.string()); |
| 74 add(tokens, exceptionState); | 74 add(tokens, exceptionState); |
| 75 } | 75 } |
| 76 | 76 |
| 77 // Optimally, this should take a Vector<AtomicString> const ref in argument but
the |
| 78 // bindings generator does not handle that. |
| 77 void DOMTokenList::add(const Vector<String>& tokens, ExceptionState& exceptionSt
ate) | 79 void DOMTokenList::add(const Vector<String>& tokens, ExceptionState& exceptionSt
ate) |
| 78 { | 80 { |
| 79 Vector<String> filteredTokens; | 81 Vector<String> filteredTokens; |
| 80 filteredTokens.reserveCapacity(tokens.size()); | 82 filteredTokens.reserveCapacity(tokens.size()); |
| 81 for (size_t i = 0; i < tokens.size(); ++i) { | 83 for (size_t i = 0; i < tokens.size(); ++i) { |
| 82 if (!validateToken(tokens[i], exceptionState)) | 84 if (!validateToken(tokens[i], exceptionState)) |
| 83 return; | 85 return; |
| 84 if (containsInternal(tokens[i])) | 86 if (containsInternal(AtomicString(tokens[i]))) |
| 85 continue; | 87 continue; |
| 86 if (filteredTokens.contains(tokens[i])) | 88 if (filteredTokens.contains(tokens[i])) |
| 87 continue; | 89 continue; |
| 88 filteredTokens.append(tokens[i]); | 90 filteredTokens.append(tokens[i]); |
| 89 } | 91 } |
| 90 | 92 |
| 91 if (filteredTokens.isEmpty()) | 93 if (filteredTokens.isEmpty()) |
| 92 return; | 94 return; |
| 93 | 95 |
| 94 setValue(addTokens(value(), filteredTokens)); | 96 setValue(addTokens(value(), filteredTokens)); |
| 95 } | 97 } |
| 96 | 98 |
| 97 void DOMTokenList::remove(const AtomicString& token, ExceptionState& exceptionSt
ate) | 99 void DOMTokenList::remove(const AtomicString& token, ExceptionState& exceptionSt
ate) |
| 98 { | 100 { |
| 99 Vector<String> tokens; | 101 Vector<String> tokens; |
| 100 tokens.append(token.string()); | 102 tokens.append(token.string()); |
| 101 remove(tokens, exceptionState); | 103 remove(tokens, exceptionState); |
| 102 } | 104 } |
| 103 | 105 |
| 106 // Optimally, this should take a Vector<AtomicString> const ref in argument but
the |
| 107 // bindings generator does not handle that. |
| 104 void DOMTokenList::remove(const Vector<String>& tokens, ExceptionState& exceptio
nState) | 108 void DOMTokenList::remove(const Vector<String>& tokens, ExceptionState& exceptio
nState) |
| 105 { | 109 { |
| 106 if (!validateTokens(tokens, exceptionState)) | 110 if (!validateTokens(tokens, exceptionState)) |
| 107 return; | 111 return; |
| 108 | 112 |
| 109 // Check using containsInternal first since it is a lot faster than going | 113 // Check using containsInternal first since it is a lot faster than going |
| 110 // through the string character by character. | 114 // through the string character by character. |
| 111 bool found = false; | 115 bool found = false; |
| 112 for (size_t i = 0; i < tokens.size(); ++i) { | 116 for (size_t i = 0; i < tokens.size(); ++i) { |
| 113 if (containsInternal(tokens[i])) { | 117 if (containsInternal(AtomicString(tokens[i]))) { |
| 114 found = true; | 118 found = true; |
| 115 break; | 119 break; |
| 116 } | 120 } |
| 117 } | 121 } |
| 118 | 122 |
| 119 if (found) | 123 if (found) |
| 120 setValue(removeTokens(value(), tokens)); | 124 setValue(removeTokens(value(), tokens)); |
| 121 } | 125 } |
| 122 | 126 |
| 123 bool DOMTokenList::toggle(const AtomicString& token, ExceptionState& exceptionSt
ate) | 127 bool DOMTokenList::toggle(const AtomicString& token, ExceptionState& exceptionSt
ate) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 154 | 158 |
| 155 void DOMTokenList::removeInternal(const AtomicString& token) | 159 void DOMTokenList::removeInternal(const AtomicString& token) |
| 156 { | 160 { |
| 157 // Check using contains first since it uses AtomicString comparisons instead | 161 // Check using contains first since it uses AtomicString comparisons instead |
| 158 // of character by character testing. | 162 // of character by character testing. |
| 159 if (!containsInternal(token)) | 163 if (!containsInternal(token)) |
| 160 return; | 164 return; |
| 161 setValue(removeToken(value(), token)); | 165 setValue(removeToken(value(), token)); |
| 162 } | 166 } |
| 163 | 167 |
| 164 String DOMTokenList::addToken(const AtomicString& input, const AtomicString& tok
en) | 168 AtomicString DOMTokenList::addToken(const AtomicString& input, const AtomicStrin
g& token) |
| 165 { | 169 { |
| 166 Vector<String> tokens; | 170 Vector<String> tokens; |
| 167 tokens.append(token.string()); | 171 tokens.append(token.string()); |
| 168 return addTokens(input, tokens); | 172 return addTokens(input, tokens); |
| 169 } | 173 } |
| 170 | 174 |
| 171 String DOMTokenList::addTokens(const AtomicString& input, const Vector<String>&
tokens) | 175 // This returns an AtomicString because it is always passed as argument to setVa
lue() and setValue() |
| 176 // takes an AtomicString in argument. |
| 177 AtomicString DOMTokenList::addTokens(const AtomicString& input, const Vector<Str
ing>& tokens) |
| 172 { | 178 { |
| 173 bool needsSpace = false; | 179 bool needsSpace = false; |
| 174 | 180 |
| 175 StringBuilder builder; | 181 StringBuilder builder; |
| 176 if (!input.isEmpty()) { | 182 if (!input.isEmpty()) { |
| 177 builder.append(input); | 183 builder.append(input); |
| 178 needsSpace = !isHTMLSpace<UChar>(input[input.length() - 1]); | 184 needsSpace = !isHTMLSpace<UChar>(input[input.length() - 1]); |
| 179 } | 185 } |
| 180 | 186 |
| 181 for (size_t i = 0; i < tokens.size(); ++i) { | 187 for (size_t i = 0; i < tokens.size(); ++i) { |
| 182 if (needsSpace) | 188 if (needsSpace) |
| 183 builder.append(' '); | 189 builder.append(' '); |
| 184 builder.append(tokens[i]); | 190 builder.append(tokens[i]); |
| 185 needsSpace = true; | 191 needsSpace = true; |
| 186 } | 192 } |
| 187 | 193 |
| 188 return builder.toString(); | 194 return builder.toAtomicString(); |
| 189 } | 195 } |
| 190 | 196 |
| 191 String DOMTokenList::removeToken(const AtomicString& input, const AtomicString&
token) | 197 AtomicString DOMTokenList::removeToken(const AtomicString& input, const AtomicSt
ring& token) |
| 192 { | 198 { |
| 193 Vector<String> tokens; | 199 Vector<String> tokens; |
| 194 tokens.append(token.string()); | 200 tokens.append(token.string()); |
| 195 return removeTokens(input, tokens); | 201 return removeTokens(input, tokens); |
| 196 } | 202 } |
| 197 | 203 |
| 198 String DOMTokenList::removeTokens(const AtomicString& input, const Vector<String
>& tokens) | 204 // This returns an AtomicString because it is always passed as argument to setVa
lue() and setValue() |
| 205 // takes an AtomicString in argument. |
| 206 AtomicString DOMTokenList::removeTokens(const AtomicString& input, const Vector<
String>& tokens) |
| 199 { | 207 { |
| 200 // Algorithm defined at http://www.whatwg.org/specs/web-apps/current-work/mu
ltipage/common-microsyntaxes.html#remove-a-token-from-a-string | 208 // Algorithm defined at http://www.whatwg.org/specs/web-apps/current-work/mu
ltipage/common-microsyntaxes.html#remove-a-token-from-a-string |
| 201 // New spec is at http://dom.spec.whatwg.org/#remove-a-token-from-a-string | 209 // New spec is at http://dom.spec.whatwg.org/#remove-a-token-from-a-string |
| 202 | 210 |
| 203 unsigned inputLength = input.length(); | 211 unsigned inputLength = input.length(); |
| 204 StringBuilder output; // 3 | 212 StringBuilder output; // 3 |
| 205 output.reserveCapacity(inputLength); | 213 output.reserveCapacity(inputLength); |
| 206 unsigned position = 0; // 4 | 214 unsigned position = 0; // 4 |
| 207 | 215 |
| 208 // Step 5 | 216 // Step 5 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 231 output.resize(j); | 239 output.resize(j); |
| 232 | 240 |
| 233 // Step 8.3 | 241 // Step 8.3 |
| 234 if (position < inputLength && !output.isEmpty()) | 242 if (position < inputLength && !output.isEmpty()) |
| 235 output.append(' '); | 243 output.append(' '); |
| 236 } else { | 244 } else { |
| 237 output.append(token); // Step 9 | 245 output.append(token); // Step 9 |
| 238 } | 246 } |
| 239 } | 247 } |
| 240 | 248 |
| 241 return output.toString(); | 249 return output.toAtomicString(); |
| 242 } | 250 } |
| 243 | 251 |
| 244 } // namespace WebCore | 252 } // namespace WebCore |
| OLD | NEW |