| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 | |
| 3 import os.path | |
| 4 import re | |
| 5 import subprocess | |
| 6 import sys | |
| 7 | |
| 8 from in_file import InFile | |
| 9 import in_generator | |
| 10 import license | |
| 11 | |
| 12 | |
| 13 HEADER_TEMPLATE = """ | |
| 14 %(license)s | |
| 15 | |
| 16 #ifndef %(class_name)s_h | |
| 17 #define %(class_name)s_h | |
| 18 | |
| 19 #include "core/css/CSSParserMode.h" | |
| 20 #include "wtf/HashFunctions.h" | |
| 21 #include "wtf/HashTraits.h" | |
| 22 #include <string.h> | |
| 23 | |
| 24 namespace WTF { | |
| 25 class AtomicString; | |
| 26 class String; | |
| 27 } | |
| 28 | |
| 29 namespace WebCore { | |
| 30 | |
| 31 enum CSSPropertyID { | |
| 32 CSSPropertyInvalid = 0, | |
| 33 CSSPropertyVariable = 1, | |
| 34 %(property_enums)s | |
| 35 }; | |
| 36 | |
| 37 const int firstCSSProperty = %(first_property_id)s; | |
| 38 const int numCSSProperties = %(properties_count)s; | |
| 39 const int lastCSSProperty = %(last_property_id)d; | |
| 40 const size_t maxCSSPropertyNameLength = %(max_name_length)d; | |
| 41 | |
| 42 const char* getPropertyName(CSSPropertyID); | |
| 43 const WTF::AtomicString& getPropertyNameAtomicString(CSSPropertyID); | |
| 44 WTF::String getPropertyNameString(CSSPropertyID); | |
| 45 WTF::String getJSPropertyName(CSSPropertyID); | |
| 46 bool isInternalProperty(CSSPropertyID id); | |
| 47 | |
| 48 inline CSSPropertyID convertToCSSPropertyID(int value) | |
| 49 { | |
| 50 ASSERT((value >= firstCSSProperty && value <= lastCSSProperty) || value == C
SSPropertyInvalid); | |
| 51 return static_cast<CSSPropertyID>(value); | |
| 52 } | |
| 53 | |
| 54 } // namespace WebCore | |
| 55 | |
| 56 namespace WTF { | |
| 57 template<> struct DefaultHash<WebCore::CSSPropertyID> { typedef IntHash<unsigned
> Hash; }; | |
| 58 template<> struct HashTraits<WebCore::CSSPropertyID> : GenericHashTraits<WebCore
::CSSPropertyID> { | |
| 59 static const bool emptyValueIsZero = true; | |
| 60 static const bool needsDestruction = false; | |
| 61 static void constructDeletedValue(WebCore::CSSPropertyID& slot) { slot = sta
tic_cast<WebCore::CSSPropertyID>(WebCore::lastCSSProperty + 1); } | |
| 62 static bool isDeletedValue(WebCore::CSSPropertyID value) { return value == (
WebCore::lastCSSProperty + 1); } | |
| 63 }; | |
| 64 } | |
| 65 | |
| 66 #endif // %(class_name)s_h | |
| 67 """ | |
| 68 | |
| 69 GPERF_TEMPLATE = """ | |
| 70 %%{ | |
| 71 %(license)s | |
| 72 | |
| 73 #include "config.h" | |
| 74 #include "%(class_name)s.h" | |
| 75 #include "core/platform/HashTools.h" | |
| 76 #include <string.h> | |
| 77 | |
| 78 #include "wtf/ASCIICType.h" | |
| 79 #include "wtf/text/AtomicString.h" | |
| 80 #include "wtf/text/WTFString.h" | |
| 81 | |
| 82 namespace WebCore { | |
| 83 static const char propertyNameStringsPool[] = { | |
| 84 %(property_name_strings)s | |
| 85 }; | |
| 86 | |
| 87 static const unsigned short propertyNameStringsOffsets[] = { | |
| 88 %(property_name_offsets)s | |
| 89 }; | |
| 90 | |
| 91 %%} | |
| 92 %%struct-type | |
| 93 struct Property; | |
| 94 %%omit-struct-type | |
| 95 %%language=C++ | |
| 96 %%readonly-tables | |
| 97 %%global-table | |
| 98 %%compare-strncmp | |
| 99 %%define class-name %(class_name)sHash | |
| 100 %%define lookup-function-name findPropertyImpl | |
| 101 %%define hash-function-name propery_hash_function | |
| 102 %%define slot-name nameOffset | |
| 103 %%define word-array-name property_wordlist | |
| 104 %%enum | |
| 105 %%%% | |
| 106 %(property_to_enum_map)s | |
| 107 %%%% | |
| 108 const Property* findProperty(register const char* str, register unsigned int len
) | |
| 109 { | |
| 110 return %(class_name)sHash::findPropertyImpl(str, len); | |
| 111 } | |
| 112 | |
| 113 const char* getPropertyName(CSSPropertyID id) | |
| 114 { | |
| 115 if (id < firstCSSProperty) | |
| 116 return 0; | |
| 117 int index = id - firstCSSProperty; | |
| 118 if (index >= numCSSProperties) | |
| 119 return 0; | |
| 120 return propertyNameStringsPool + propertyNameStringsOffsets[index]; | |
| 121 } | |
| 122 | |
| 123 const AtomicString& getPropertyNameAtomicString(CSSPropertyID id) | |
| 124 { | |
| 125 if (id < firstCSSProperty) | |
| 126 return nullAtom; | |
| 127 int index = id - firstCSSProperty; | |
| 128 if (index >= numCSSProperties) | |
| 129 return nullAtom; | |
| 130 | |
| 131 static AtomicString* propertyStrings = new AtomicString[numCSSProperties]; /
/ Intentionally never destroyed. | |
| 132 AtomicString& propertyString = propertyStrings[index]; | |
| 133 if (propertyString.isNull()) { | |
| 134 const char* propertyName = propertyNameStringsPool + propertyNameStrings
Offsets[index]; | |
| 135 propertyString = AtomicString(propertyName, strlen(propertyName), Atomic
String::ConstructFromLiteral); | |
| 136 } | |
| 137 return propertyString; | |
| 138 } | |
| 139 | |
| 140 String getPropertyNameString(CSSPropertyID id) | |
| 141 { | |
| 142 // We share the StringImpl with the AtomicStrings. | |
| 143 return getPropertyNameAtomicString(id).string(); | |
| 144 } | |
| 145 | |
| 146 String getJSPropertyName(CSSPropertyID id) | |
| 147 { | |
| 148 char result[maxCSSPropertyNameLength + 1]; | |
| 149 const char* cssPropertyName = getPropertyName(id); | |
| 150 const char* propertyNamePointer = cssPropertyName; | |
| 151 if (!propertyNamePointer) | |
| 152 return emptyString(); | |
| 153 | |
| 154 char* resultPointer = result; | |
| 155 while (char character = *propertyNamePointer++) { | |
| 156 if (character == '-') { | |
| 157 char nextCharacter = *propertyNamePointer++; | |
| 158 if (!nextCharacter) | |
| 159 break; | |
| 160 character = (propertyNamePointer - 2 != cssPropertyName) ? toASCIIUp
per(nextCharacter) : nextCharacter; | |
| 161 } | |
| 162 *resultPointer++ = character; | |
| 163 } | |
| 164 *resultPointer = '\\0'; | |
| 165 return String(result); | |
| 166 } | |
| 167 | |
| 168 bool isInternalProperty(CSSPropertyID id) | |
| 169 { | |
| 170 switch (id) { | |
| 171 %(internal_properties)s | |
| 172 return true; | |
| 173 default: | |
| 174 return false; | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 } // namespace WebCore | |
| 179 """ | |
| 180 | |
| 181 | |
| 182 class CSSPropertiesWriter(in_generator.Writer): | |
| 183 class_name = "CSSPropertyNames" | |
| 184 defaults = { | |
| 185 'alias_for': None, | |
| 186 'condition': None, | |
| 187 'is_internal': False, | |
| 188 } | |
| 189 | |
| 190 def __init__(self, file_paths, enabled_conditions): | |
| 191 in_generator.Writer.__init__(self, file_paths, enabled_conditions) | |
| 192 self._outputs = {(self.class_name + ".h"): self.generate_header, | |
| 193 (self.class_name + ".cpp"): self.generate_implementatio
n, | |
| 194 } | |
| 195 | |
| 196 all_properties = self.in_file.name_dictionaries | |
| 197 self._aliases = filter(lambda property: property['alias_for'], all_prope
rties) | |
| 198 for offset, property in enumerate(self._aliases): | |
| 199 # Aliases use the enum_name that they are an alias for. | |
| 200 property['enum_name'] = self._enum_name_from_property_name(property[
'alias_for']) | |
| 201 # Aliases do not get an enum_value. | |
| 202 | |
| 203 self._properties = filter(lambda property: not property['alias_for'] and
not property['condition'] or property['condition'] in self._enabled_conditions,
all_properties) | |
| 204 if len(self._properties) > 1024: | |
| 205 print "ERROR : There is more than 1024 CSS Properties, you need to u
pdate CSSProperty.h/StylePropertyMetadata m_propertyID accordingly." | |
| 206 exit(1) | |
| 207 self._first_property_id = 2 # We start after CSSPropertyInvalid and CSS
PropertyVariable. | |
| 208 property_id = self._first_property_id | |
| 209 for offset, property in enumerate(self._properties): | |
| 210 property['enum_name'] = self._enum_name_from_property_name(property[
'name']) | |
| 211 property['enum_value'] = self._first_property_id + offset | |
| 212 if property['name'].startswith('-internal-'): | |
| 213 property['is_internal'] = True | |
| 214 | |
| 215 def _enum_name_from_property_name(self, property_name): | |
| 216 return "CSSProperty" + re.sub(r'(^[^-])|-(.)', lambda match: (match.grou
p(1) or match.group(2)).upper(), property_name) | |
| 217 | |
| 218 def _enum_declaration(self, property): | |
| 219 return " %(enum_name)s = %(enum_value)s," % property | |
| 220 | |
| 221 def generate_header(self): | |
| 222 return HEADER_TEMPLATE % { | |
| 223 'license': license.license_for_generated_cpp(), | |
| 224 'class_name': self.class_name, | |
| 225 'property_enums': "\n".join(map(self._enum_declaration, self._proper
ties)), | |
| 226 'first_property_id': self._first_property_id, | |
| 227 'properties_count': len(self._properties), | |
| 228 'last_property_id': self._first_property_id + len(self._properties)
- 1, | |
| 229 'max_name_length': reduce(max, map(len, map(lambda property: propert
y['name'], self._properties))), | |
| 230 } | |
| 231 | |
| 232 def _case_properties(self, property): | |
| 233 return "case %(enum_name)s:" % property | |
| 234 | |
| 235 def generate_implementation(self): | |
| 236 property_offsets = [] | |
| 237 current_offset = 0 | |
| 238 for property in self._properties: | |
| 239 property_offsets.append(current_offset) | |
| 240 current_offset += len(property["name"]) + 1 | |
| 241 | |
| 242 gperf_input = GPERF_TEMPLATE % { | |
| 243 'license': license.license_for_generated_cpp(), | |
| 244 'class_name': self.class_name, | |
| 245 'property_name_strings': '\n'.join(map(lambda property: ' "%(name
)s\\0"' % property, self._properties)), | |
| 246 'property_name_offsets': '\n'.join(map(lambda offset: ' %d,' % of
fset, property_offsets)), | |
| 247 'property_to_enum_map': '\n'.join(map(lambda property: '%(name)s, %(
enum_name)s' % property, self._properties + self._aliases)), | |
| 248 'internal_properties': '\n'.join(map(self._case_properties, filter(l
ambda property: property['is_internal'], self._properties))), | |
| 249 } | |
| 250 # FIXME: If we could depend on Python 2.7, we would use subprocess.check
_output | |
| 251 gperf_args = ['gperf', '--key-positions=*', '-P', '-D', '-n', '-s', '2'] | |
| 252 gperf = subprocess.Popen(gperf_args, stdin=subprocess.PIPE, stdout=subpr
ocess.PIPE) | |
| 253 return gperf.communicate(gperf_input)[0] | |
| 254 | |
| 255 | |
| 256 if __name__ == "__main__": | |
| 257 in_generator.Maker(CSSPropertiesWriter).main(sys.argv) | |
| OLD | NEW |