2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #include "DatasetDOMStringMap.h"
29 #include "Attribute.h"
31 #include "ExceptionCode.h"
32 #include "NamedNodeMap.h"
33 #include <wtf/ASCIICType.h>
34 #include <wtf/text/StringBuilder.h>
38 static bool isValidAttributeName(const String& name)
40 if (!name.startsWith("data-"))
43 const UChar* characters = name.characters();
44 unsigned length = name.length();
45 for (unsigned i = 5; i < length; ++i) {
46 if (isASCIIUpper(characters[i]))
53 static String convertAttributeNameToPropertyName(const String& name)
55 StringBuilder stringBuilder;
57 const UChar* characters = name.characters();
58 unsigned length = name.length();
59 for (unsigned i = 5; i < length; ++i) {
60 UChar character = characters[i];
62 stringBuilder.append(character);
64 if ((i + 1 < length) && isASCIILower(characters[i + 1])) {
65 stringBuilder.append(toASCIIUpper(characters[i + 1]));
68 stringBuilder.append(character);
72 return stringBuilder.toString();
75 static bool propertyNameMatchesAttributeName(const String& propertyName, const String& attributeName)
77 if (!attributeName.startsWith("data-"))
80 const UChar* property = propertyName.characters();
81 const UChar* attribute = attributeName.characters();
82 unsigned propertyLength = propertyName.length();
83 unsigned attributeLength = attributeName.length();
87 bool wordBoundary = false;
88 while (a < attributeLength && p < propertyLength) {
89 if (attribute[a] == '-' && a + 1 < attributeLength && attribute[a + 1] != '-')
92 if ((wordBoundary ? toASCIIUpper(attribute[a]) : attribute[a]) != property[p])
100 return (a == attributeLength && p == propertyLength);
103 static bool isValidPropertyName(const String& name)
105 const UChar* characters = name.characters();
106 unsigned length = name.length();
107 for (unsigned i = 0; i < length; ++i) {
108 if (characters[i] == '-' && (i + 1 < length) && isASCIILower(characters[i + 1]))
114 static String convertPropertyNameToAttributeName(const String& name)
116 StringBuilder builder;
117 builder.append("data-");
119 const UChar* characters = name.characters();
120 unsigned length = name.length();
121 for (unsigned i = 0; i < length; ++i) {
122 UChar character = characters[i];
123 if (isASCIIUpper(character)) {
125 builder.append(toASCIILower(character));
127 builder.append(character);
130 return builder.toString();
133 void DatasetDOMStringMap::ref()
138 void DatasetDOMStringMap::deref()
143 void DatasetDOMStringMap::getNames(Vector<String>& names)
145 NamedNodeMap* attributeMap = m_element->attributes(true);
147 unsigned length = attributeMap->length();
148 for (unsigned i = 0; i < length; i++) {
149 Attribute* attribute = attributeMap->attributeItem(i);
150 if (isValidAttributeName(attribute->localName()))
151 names.append(convertAttributeNameToPropertyName(attribute->localName()));
156 String DatasetDOMStringMap::item(const String& name)
158 NamedNodeMap* attributeMap = m_element->attributes(true);
160 unsigned length = attributeMap->length();
161 for (unsigned i = 0; i < length; i++) {
162 Attribute* attribute = attributeMap->attributeItem(i);
163 if (propertyNameMatchesAttributeName(name, attribute->localName()))
164 return attribute->value();
171 bool DatasetDOMStringMap::contains(const String& name)
173 NamedNodeMap* attributeMap = m_element->attributes(true);
175 unsigned length = attributeMap->length();
176 for (unsigned i = 0; i < length; i++) {
177 Attribute* attribute = attributeMap->attributeItem(i);
178 if (propertyNameMatchesAttributeName(name, attribute->localName()))
185 void DatasetDOMStringMap::setItem(const String& name, const String& value, ExceptionCode& ec)
187 if (!isValidPropertyName(name)) {
192 m_element->setAttribute(convertPropertyNameToAttributeName(name), value, ec);
195 void DatasetDOMStringMap::deleteItem(const String& name, ExceptionCode& ec)
197 if (!isValidPropertyName(name)) {
203 m_element->removeAttribute(convertPropertyNameToAttributeName(name), dummy);
206 } // namespace WebCore