Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / build / scripts / make_css_property_names.py
1 #!/usr/bin/env python
2
3 import subprocess
4 import sys
5
6 import css_properties
7 import in_generator
8 import license
9
10
11 HEADER_TEMPLATE = """
12 %(license)s
13
14 #ifndef %(class_name)s_h
15 #define %(class_name)s_h
16
17 #include "core/css/parser/CSSParserMode.h"
18 #include "wtf/HashFunctions.h"
19 #include "wtf/HashTraits.h"
20 #include <string.h>
21
22 namespace WTF {
23 class AtomicString;
24 class String;
25 }
26
27 namespace blink {
28
29 enum CSSPropertyID {
30     CSSPropertyInvalid = 0,
31 %(property_enums)s
32 };
33
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 size_t maxCSSPropertyNameLength = %(max_name_length)d;
38
39 const char* getPropertyName(CSSPropertyID);
40 const WTF::AtomicString& getPropertyNameAtomicString(CSSPropertyID);
41 WTF::String getPropertyNameString(CSSPropertyID);
42 WTF::String getJSPropertyName(CSSPropertyID);
43 bool isInternalProperty(CSSPropertyID id);
44
45 inline CSSPropertyID convertToCSSPropertyID(int value)
46 {
47     ASSERT((value >= firstCSSProperty && value <= lastCSSProperty) || value == CSSPropertyInvalid);
48     return static_cast<CSSPropertyID>(value);
49 }
50
51 } // namespace blink
52
53 namespace WTF {
54 template<> struct DefaultHash<blink::CSSPropertyID> { typedef IntHash<unsigned> Hash; };
55 template<> struct HashTraits<blink::CSSPropertyID> : GenericHashTraits<blink::CSSPropertyID> {
56     static const bool emptyValueIsZero = true;
57     static const bool needsDestruction = false;
58     static void constructDeletedValue(blink::CSSPropertyID& slot, bool) { slot = static_cast<blink::CSSPropertyID>(blink::lastCSSProperty + 1); }
59     static bool isDeletedValue(blink::CSSPropertyID value) { return value == (blink::lastCSSProperty + 1); }
60 };
61 }
62
63 #endif // %(class_name)s_h
64 """
65
66 GPERF_TEMPLATE = """
67 %%{
68 %(license)s
69
70 #include "config.h"
71 #include "%(class_name)s.h"
72 #include "core/css/HashTools.h"
73 #include <string.h>
74
75 #include "wtf/ASCIICType.h"
76 #include "wtf/text/AtomicString.h"
77 #include "wtf/text/WTFString.h"
78
79 namespace blink {
80 static const char propertyNameStringsPool[] = {
81 %(property_name_strings)s
82 };
83
84 static const unsigned short propertyNameStringsOffsets[] = {
85 %(property_name_offsets)s
86 };
87
88 %%}
89 %%struct-type
90 struct Property;
91 %%omit-struct-type
92 %%language=C++
93 %%readonly-tables
94 %%global-table
95 %%compare-strncmp
96 %%define class-name %(class_name)sHash
97 %%define lookup-function-name findPropertyImpl
98 %%define hash-function-name property_hash_function
99 %%define slot-name nameOffset
100 %%define word-array-name property_word_list
101 %%enum
102 %%%%
103 %(property_to_enum_map)s
104 %%%%
105 const Property* findProperty(register const char* str, register unsigned int len)
106 {
107     return %(class_name)sHash::findPropertyImpl(str, len);
108 }
109
110 const char* getPropertyName(CSSPropertyID id)
111 {
112     if (id < firstCSSProperty)
113         return 0;
114     int index = id - firstCSSProperty;
115     if (index >= numCSSProperties)
116         return 0;
117     return propertyNameStringsPool + propertyNameStringsOffsets[index];
118 }
119
120 const AtomicString& getPropertyNameAtomicString(CSSPropertyID id)
121 {
122     if (id < firstCSSProperty)
123         return nullAtom;
124     int index = id - firstCSSProperty;
125     if (index >= numCSSProperties)
126         return nullAtom;
127
128     static AtomicString* propertyStrings = new AtomicString[numCSSProperties]; // Intentionally never destroyed.
129     AtomicString& propertyString = propertyStrings[index];
130     if (propertyString.isNull()) {
131         const char* propertyName = propertyNameStringsPool + propertyNameStringsOffsets[index];
132         propertyString = AtomicString(propertyName, strlen(propertyName), AtomicString::ConstructFromLiteral);
133     }
134     return propertyString;
135 }
136
137 String getPropertyNameString(CSSPropertyID id)
138 {
139     // We share the StringImpl with the AtomicStrings.
140     return getPropertyNameAtomicString(id).string();
141 }
142
143 String getJSPropertyName(CSSPropertyID id)
144 {
145     char result[maxCSSPropertyNameLength + 1];
146     const char* cssPropertyName = getPropertyName(id);
147     const char* propertyNamePointer = cssPropertyName;
148     if (!propertyNamePointer)
149         return emptyString();
150
151     char* resultPointer = result;
152     while (char character = *propertyNamePointer++) {
153         if (character == '-') {
154             char nextCharacter = *propertyNamePointer++;
155             if (!nextCharacter)
156                 break;
157             character = (propertyNamePointer - 2 != cssPropertyName) ? toASCIIUpper(nextCharacter) : nextCharacter;
158         }
159         *resultPointer++ = character;
160     }
161     *resultPointer = '\\0';
162     return String(result);
163 }
164
165 bool isInternalProperty(CSSPropertyID id)
166 {
167     switch (id) {
168         %(internal_properties)s
169             return true;
170         default:
171             return false;
172     }
173 }
174
175 } // namespace blink
176 """
177
178
179 class CSSPropertyNamesWriter(css_properties.CSSProperties):
180     class_name = "CSSPropertyNames"
181
182     def __init__(self, in_file_path):
183         super(CSSPropertyNamesWriter, self).__init__(in_file_path)
184         self._outputs = {(self.class_name + ".h"): self.generate_header,
185                          (self.class_name + ".cpp"): self.generate_implementation,
186                         }
187
188     def _enum_declaration(self, property):
189         return "    %(property_id)s = %(enum_value)s," % property
190
191     def generate_header(self):
192         return HEADER_TEMPLATE % {
193             'license': license.license_for_generated_cpp(),
194             'class_name': self.class_name,
195             'property_enums': "\n".join(map(self._enum_declaration, self._properties_list)),
196             'first_property_id': self._first_enum_value,
197             'properties_count': len(self._properties),
198             'last_property_id': self._first_enum_value + len(self._properties) - 1,
199             'max_name_length': max(map(len, self._properties)),
200         }
201
202     def generate_implementation(self):
203         property_offsets = []
204         current_offset = 0
205         for property in self._properties_list:
206             property_offsets.append(current_offset)
207             current_offset += len(property["name"]) + 1
208
209         css_name_and_enum_pairs = [(property['name'], property_id) for property_id, property in self._properties.items()]
210         for name, aliased_name in self._aliases.items():
211             css_name_and_enum_pairs.append((name, css_properties.css_name_to_enum(aliased_name)))
212
213         gperf_input = GPERF_TEMPLATE % {
214             'license': license.license_for_generated_cpp(),
215             'class_name': self.class_name,
216             'property_name_strings': '\n'.join(map(lambda property: '    "%(name)s\\0"' % property, self._properties_list)),
217             'property_name_offsets': '\n'.join(map(lambda offset: '    %d,' % offset, property_offsets)),
218             'property_to_enum_map': '\n'.join(map(lambda property: '%s, %s' % property, css_name_and_enum_pairs)),
219             'internal_properties': '\n'.join("case %s:" % property_id for property_id, property in self._properties.items() if property['is_internal']),
220         }
221         # FIXME: If we could depend on Python 2.7, we would use subprocess.check_output
222         gperf_args = [self.gperf_path, '--key-positions=*', '-P', '-n']
223         gperf_args.extend(['-m', '50'])  # Pick best of 50 attempts.
224         gperf_args.append('-D')  # Allow duplicate hashes -> More compact code.
225         gperf = subprocess.Popen(gperf_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
226         return gperf.communicate(gperf_input)[0]
227
228
229 if __name__ == "__main__":
230     in_generator.Maker(CSSPropertyNamesWriter).main(sys.argv)