14 #ifndef %(class_name)s_h
15 #define %(class_name)s_h
17 #include "core/css/parser/CSSParserMode.h"
18 #include "wtf/HashFunctions.h"
19 #include "wtf/HashTraits.h"
30 CSSPropertyInvalid = 0,
34 const int firstCSSProperty = %(first_property_id)s;
35 const int numCSSProperties = %(properties_count)s;
36 const int lastCSSProperty = %(last_property_id)d;
37 const int lastUnresolvedCSSProperty = %(last_unresolved_property_id)d;
38 const size_t maxCSSPropertyNameLength = %(max_name_length)d;
40 const char* getPropertyName(CSSPropertyID);
41 const WTF::AtomicString& getPropertyNameAtomicString(CSSPropertyID);
42 WTF::String getPropertyNameString(CSSPropertyID);
43 WTF::String getJSPropertyName(CSSPropertyID);
45 inline CSSPropertyID convertToCSSPropertyID(int value)
47 ASSERT((value >= firstCSSProperty && value <= lastCSSProperty) || value == CSSPropertyInvalid);
48 return static_cast<CSSPropertyID>(value);
51 inline CSSPropertyID resolveCSSPropertyID(CSSPropertyID id)
53 return convertToCSSPropertyID(id & ~512);
56 inline bool isPropertyAlias(CSSPropertyID id) { return id & 512; }
58 CSSPropertyID unresolvedCSSPropertyID(const WTF::String&);
60 CSSPropertyID cssPropertyID(const WTF::String&);
65 template<> struct DefaultHash<blink::CSSPropertyID> { typedef IntHash<unsigned> Hash; };
66 template<> struct HashTraits<blink::CSSPropertyID> : GenericHashTraits<blink::CSSPropertyID> {
67 static const bool emptyValueIsZero = true;
68 static void constructDeletedValue(blink::CSSPropertyID& slot, bool) { slot = static_cast<blink::CSSPropertyID>(blink::lastUnresolvedCSSProperty + 1); }
69 static bool isDeletedValue(blink::CSSPropertyID value) { return value == (blink::lastUnresolvedCSSProperty + 1); }
73 #endif // %(class_name)s_h
81 #include "%(class_name)s.h"
82 #include "core/css/HashTools.h"
85 #include "wtf/ASCIICType.h"
86 #include "wtf/text/AtomicString.h"
87 #include "wtf/text/WTFString.h"
90 static const char propertyNameStringsPool[] = {
91 %(property_name_strings)s
94 static const unsigned short propertyNameStringsOffsets[] = {
95 %(property_name_offsets)s
106 %%define class-name %(class_name)sHash
107 %%define lookup-function-name findPropertyImpl
108 %%define hash-function-name property_hash_function
109 %%define slot-name nameOffset
110 %%define word-array-name property_word_list
113 %(property_to_enum_map)s
115 const Property* findProperty(register const char* str, register unsigned int len)
117 return %(class_name)sHash::findPropertyImpl(str, len);
120 const char* getPropertyName(CSSPropertyID id)
122 ASSERT(id >= firstCSSProperty && id <= lastUnresolvedCSSProperty);
123 int index = id - firstCSSProperty;
124 return propertyNameStringsPool + propertyNameStringsOffsets[index];
127 const AtomicString& getPropertyNameAtomicString(CSSPropertyID id)
129 ASSERT(id >= firstCSSProperty && id <= lastUnresolvedCSSProperty);
130 int index = id - firstCSSProperty;
131 static AtomicString* propertyStrings = new AtomicString[lastUnresolvedCSSProperty]; // Intentionally never destroyed.
132 AtomicString& propertyString = propertyStrings[index];
133 if (propertyString.isNull()) {
134 const char* propertyName = propertyNameStringsPool + propertyNameStringsOffsets[index];
135 propertyString = AtomicString(propertyName, strlen(propertyName), AtomicString::ConstructFromLiteral);
137 return propertyString;
140 String getPropertyNameString(CSSPropertyID id)
142 // We share the StringImpl with the AtomicStrings.
143 return getPropertyNameAtomicString(id).string();
146 String getJSPropertyName(CSSPropertyID id)
148 char result[maxCSSPropertyNameLength + 1];
149 const char* cssPropertyName = getPropertyName(id);
150 const char* propertyNamePointer = cssPropertyName;
151 if (!propertyNamePointer)
152 return emptyString();
154 char* resultPointer = result;
155 while (char character = *propertyNamePointer++) {
156 if (character == '-') {
157 char nextCharacter = *propertyNamePointer++;
160 character = (propertyNamePointer - 2 != cssPropertyName) ? toASCIIUpper(nextCharacter) : nextCharacter;
162 *resultPointer++ = character;
164 *resultPointer = '\\0';
165 return String(result);
168 CSSPropertyID cssPropertyID(const String& string)
170 return resolveCSSPropertyID(unresolvedCSSPropertyID(string));
177 class CSSPropertyNamesWriter(css_properties
.CSSProperties
):
178 class_name
= "CSSPropertyNames"
180 def __init__(self
, in_file_path
):
181 super(CSSPropertyNamesWriter
, self
).__init
__(in_file_path
)
182 self
._outputs
= {(self
.class_name
+ ".h"): self
.generate_header
,
183 (self
.class_name
+ ".cpp"): self
.generate_implementation
,
186 def _enum_declaration(self
, property):
187 return " %(property_id)s = %(enum_value)s," % property
189 def generate_header(self
):
190 return HEADER_TEMPLATE
% {
191 'license': license
.license_for_generated_cpp(),
192 'class_name': self
.class_name
,
193 'property_enums': "\n".join(map(self
._enum
_declaration
, self
._properties
_including
_aliases
)),
194 'first_property_id': self
._first
_enum
_value
,
195 'properties_count': len(self
._properties
),
196 'last_property_id': self
._first
_enum
_value
+ len(self
._properties
) - 1,
197 'last_unresolved_property_id': max(property["enum_value"] for property in self
._properties
_including
_aliases
),
198 'max_name_length': max(map(len, self
._properties
)),
201 def generate_implementation(self
):
202 enum_value_to_name
= {property['enum_value']: property['name'] for property in self
._properties
_including
_aliases
}
203 property_offsets
= []
206 for enum_value
in range(self
._first
_enum
_value
, max(enum_value_to_name
) + 1):
207 property_offsets
.append(current_offset
)
208 if enum_value
in enum_value_to_name
:
209 name
= enum_value_to_name
[enum_value
]
210 property_names
.append(name
)
211 current_offset
+= len(name
) + 1
213 css_name_and_enum_pairs
= [(property['name'], property['property_id']) for property in self
._properties
_including
_aliases
]
215 gperf_input
= GPERF_TEMPLATE
% {
216 'license': license
.license_for_generated_cpp(),
217 'class_name': self
.class_name
,
218 'property_name_strings': '\n'.join(' "%s\\0"' % name
for name
in property_names
),
219 'property_name_offsets': '\n'.join(' %d,' % offset
for offset
in property_offsets
),
220 'property_to_enum_map': '\n'.join('%s, %s' % property for property in css_name_and_enum_pairs
),
222 # FIXME: If we could depend on Python 2.7, we would use subprocess.check_output
223 gperf_args
= [self
.gperf_path
, '--key-positions=*', '-P', '-n']
224 gperf_args
.extend(['-m', '50']) # Pick best of 50 attempts.
225 gperf_args
.append('-D') # Allow duplicate hashes -> More compact code.
226 gperf
= subprocess
.Popen(gperf_args
, stdin
=subprocess
.PIPE
, stdout
=subprocess
.PIPE
, universal_newlines
=True)
227 return gperf
.communicate(gperf_input
)[0]
230 if __name__
== "__main__":
231 in_generator
.Maker(CSSPropertyNamesWriter
).main(sys
.argv
)