15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010 Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1.  Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2.  Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/DOMTokenList.h"
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28df95704c49daea886ddad70775bda23618d6274dBen Murdoch#include "bindings/v8/ExceptionState.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/ExceptionCode.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/parser/HTMLParserIdioms.h"
31e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/text/StringBuilder.h"
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35df95704c49daea886ddad70775bda23618d6274dBen Murdochbool DOMTokenList::validateToken(const AtomicString& token, ExceptionState& es)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (token.isEmpty()) {
38df95704c49daea886ddad70775bda23618d6274dBen Murdoch        es.throwDOMException(SyntaxError);
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned length = token.length();
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < length; ++i) {
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (isHTMLSpace(token[i])) {
45df95704c49daea886ddad70775bda23618d6274dBen Murdoch            es.throwDOMException(InvalidCharacterError);
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53df95704c49daea886ddad70775bda23618d6274dBen Murdochbool DOMTokenList::validateTokens(const Vector<String>& tokens, ExceptionState& es)
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < tokens.size(); ++i) {
56df95704c49daea886ddad70775bda23618d6274dBen Murdoch        if (!validateToken(tokens[i], es))
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
63df95704c49daea886ddad70775bda23618d6274dBen Murdochbool DOMTokenList::contains(const AtomicString& token, ExceptionState& es) const
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
65df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (!validateToken(token, es))
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return containsInternal(token);
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
70df95704c49daea886ddad70775bda23618d6274dBen Murdochvoid DOMTokenList::add(const AtomicString& token, ExceptionState& es)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<String> tokens;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    tokens.append(token.string());
74df95704c49daea886ddad70775bda23618d6274dBen Murdoch    add(tokens, es);
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
77df95704c49daea886ddad70775bda23618d6274dBen Murdochvoid DOMTokenList::add(const Vector<String>& tokens, ExceptionState& es)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<String> filteredTokens;
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < tokens.size(); ++i) {
81df95704c49daea886ddad70775bda23618d6274dBen Murdoch        if (!validateToken(tokens[i], es))
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!containsInternal(tokens[i]))
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            filteredTokens.append(tokens[i]);
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (filteredTokens.isEmpty())
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setValue(addTokens(value(), filteredTokens));
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
93df95704c49daea886ddad70775bda23618d6274dBen Murdochvoid DOMTokenList::remove(const AtomicString& token, ExceptionState& es)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<String> tokens;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    tokens.append(token.string());
97df95704c49daea886ddad70775bda23618d6274dBen Murdoch    remove(tokens, es);
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
100df95704c49daea886ddad70775bda23618d6274dBen Murdochvoid DOMTokenList::remove(const Vector<String>& tokens, ExceptionState& es)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
102df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (!validateTokens(tokens, es))
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check using containsInternal first since it is a lot faster than going
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // through the string character by character.
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool found = false;
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < tokens.size(); ++i) {
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (containsInternal(tokens[i])) {
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            found = true;
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (found)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setValue(removeTokens(value(), tokens));
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
119df95704c49daea886ddad70775bda23618d6274dBen Murdochbool DOMTokenList::toggle(const AtomicString& token, ExceptionState& es)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
121df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (!validateToken(token, es))
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (containsInternal(token)) {
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeInternal(token);
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addInternal(token);
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
132df95704c49daea886ddad70775bda23618d6274dBen Murdochbool DOMTokenList::toggle(const AtomicString& token, bool force, ExceptionState& es)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
134df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (!validateToken(token, es))
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (force)
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        addInternal(token);
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeInternal(token);
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return force;
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DOMTokenList::addInternal(const AtomicString& token)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!containsInternal(token))
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setValue(addToken(value(), token));
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DOMTokenList::removeInternal(const AtomicString& token)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check using contains first since it uses AtomicString comparisons instead
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // of character by character testing.
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!containsInternal(token))
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setValue(removeToken(value(), token));
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String DOMTokenList::addToken(const AtomicString& input, const AtomicString& token)
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<String> tokens;
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    tokens.append(token.string());
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return addTokens(input, tokens);
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String DOMTokenList::addTokens(const AtomicString& input, const Vector<String>& tokens)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool needsSpace = false;
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringBuilder builder;
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!input.isEmpty()) {
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        builder.append(input);
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        needsSpace = !isHTMLSpace(input[input.length() - 1]);
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < tokens.size(); ++i) {
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (needsSpace)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            builder.append(' ');
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        builder.append(tokens[i]);
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        needsSpace = true;
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return builder.toString();
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String DOMTokenList::removeToken(const AtomicString& input, const AtomicString& token)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<String> tokens;
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    tokens.append(token.string());
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return removeTokens(input, tokens);
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String DOMTokenList::removeTokens(const AtomicString& input, const Vector<String>& tokens)
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Algorithm defined at http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#remove-a-token-from-a-string
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // New spec is at http://dom.spec.whatwg.org/#remove-a-token-from-a-string
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned inputLength = input.length();
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringBuilder output; // 3
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    output.reserveCapacity(inputLength);
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned position = 0; // 4
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Step 5
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (position < inputLength) {
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (isHTMLSpace(input[position])) { // 6
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            output.append(input[position++]); // 6.1, 6.2
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue; // 6.3
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Step 7
2127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        StringBuilder tokenBuilder;
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (position < inputLength && isNotHTMLSpace(input[position]))
2147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            tokenBuilder.append(input[position++]);
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Step 8
2177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        String token = tokenBuilder.toString();
2187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (tokens.contains(token)) {
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Step 8.1
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            while (position < inputLength && isHTMLSpace(input[position]))
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ++position;
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Step 8.2
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            size_t j = output.length();
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            while (j > 0 && isHTMLSpace(output[j - 1]))
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                --j;
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            output.resize(j);
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Step 8.3
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (position < inputLength && !output.isEmpty())
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                output.append(' ');
2327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        } else {
2337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            output.append(token); // Step 9
2347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return output.toString();
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
241