| #!/usr/bin/env python3 |
| # |
| # Copyright (C) 2024 Apple Inc. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| # THE POSSIBILITY OF SUCH DAMAGE. |
| |
| import argparse |
| import json |
| |
| |
| def lowercase_first_letter(string): |
| return string[0].lower() + string[1:] if len(string) and string[1].islower() else string |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser(description='Generate EventNames.h') |
| parser.add_argument('--event-names') |
| args = parser.parse_args() |
| |
| with open(args.event_names, 'r', encoding='utf-8') as event_names_file: |
| event_names_input = json.load(event_names_file) |
| |
| with open('EventNames.h', 'w') as output_file: |
| def write(text): |
| output_file.write(text) |
| |
| def writeln(text): |
| write(text + '\n') |
| |
| writeln('''/* |
| * Copyright (C) 2005-2024 Apple Inc. All rights reserved. |
| * Copyright (C) 2006 Jon Shier (jshier@iastate.edu) |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| * |
| */ |
| |
| #pragma once |
| |
| #include <WebCore/ThreadGlobalData.h> |
| #include <array> |
| #include <functional> |
| #include <wtf/HashSet.h> |
| #include <wtf/OptionSet.h> |
| #include <wtf/RobinHoodHashMap.h> |
| #include <wtf/text/AtomString.h> |
| #include <wtf/text/AtomStringHash.h> |
| |
| namespace WebCore { |
| |
| enum class EventType : uint16_t { |
| custom = 0,''') |
| |
| category_map = {} |
| for name in sorted(event_names_input.keys()): |
| entry = event_names_input[name] |
| for event_category in entry.get('categories', []): |
| category_map.setdefault(event_category, []) |
| category_map[event_category].append(name) |
| conditional = entry.get('conditional', None) |
| if conditional: |
| writeln(f'#if {conditional}') |
| writeln(f' {name},') |
| if conditional: |
| writeln('#endif') |
| |
| writeln('''}; |
| |
| enum class EventCategory : uint16_t {''') |
| |
| bit_shift = 0 |
| for category in sorted(category_map.keys()): |
| writeln(f' {category} = 1u << {bit_shift},') |
| bit_shift += 1 |
| |
| writeln('''}; |
| |
| class EventTypeInfo { |
| public: |
| enum class DefaultEventHandler : bool { No, Yes }; |
| |
| EventTypeInfo() |
| : m_type(EventType::custom) |
| { } |
| |
| EventTypeInfo(EventType type, OptionSet<EventCategory> categories, DefaultEventHandler defaultEventHandler) |
| : m_type(type) |
| , m_categories(categories.toRaw()) |
| , m_hasDefaultEventHandler(defaultEventHandler == DefaultEventHandler::Yes) |
| { } |
| |
| EventType type() const { return static_cast<EventType>(m_type); } |
| bool isInCategory(EventCategory category) const { return OptionSet<EventCategory>::fromRaw(m_categories).contains(category); } |
| bool hasDefaultEventHandler() const { return m_hasDefaultEventHandler; } |
| |
| private: |
| EventType m_type; |
| uint16_t m_categories : 15 { 0 }; |
| uint16_t m_hasDefaultEventHandler : 1 { false }; |
| }; |
| |
| struct EventNames { |
| WTF_MAKE_NONCOPYABLE(EventNames); WTF_DEPRECATED_MAKE_FAST_ALLOCATED(EventNames); |
| public:''') |
| |
| for name in sorted(event_names_input.keys()): |
| entry = event_names_input[name] |
| conditional = entry.get('conditional', None) |
| if conditional: |
| writeln(f'#if {conditional}') |
| writeln(f' const AtomString {name}Event;') |
| if conditional: |
| writeln('#endif') |
| |
| writeln(''' |
| EventTypeInfo typeInfoForEvent(const AtomString&) const; |
| |
| template<class... Args> |
| static std::unique_ptr<EventNames> create(Args&&... args) |
| { |
| return std::unique_ptr<EventNames>(new EventNames(std::forward<Args>(args)...)); |
| } |
| ''') |
| writeln(f' std::array<const AtomString, {len(event_names_input)}> allEventNames() const;') |
| writeln(f' WTF::HashSet<AtomString> allEventHandlerNames() const;') |
| writeln(f'') |
| writeln(f' static constexpr std::array timedEvents {{') |
| for name in category_map['EventTimingEligible']: |
| entry = event_names_input[name] |
| conditional = entry.get('conditional', None) |
| writeln(f'#if {conditional}') if conditional else None |
| writeln(f' EventType::{name},') |
| writeln(f'#endif') if conditional else None |
| writeln(f' }};') |
| writeln(f'') |
| writeln(f' const AtomString& eventNameFromEventType(EventType) const;') |
| writeln(''' |
| private: |
| EventNames(); |
| |
| MemoryCompactLookupOnlyRobinHoodHashMap<AtomString, EventTypeInfo> m_typeInfoMap; |
| }; |
| |
| const EventNames& eventNames(); |
| |
| inline const EventNames& eventNames() |
| { |
| return threadGlobalDataSingleton().eventNames(); |
| } |
| |
| inline EventTypeInfo EventNames::typeInfoForEvent(const AtomString& eventType) const |
| { |
| return m_typeInfoMap.inlineGet(eventType); |
| } |
| |
| } // namespace WebCore''') |
| |
| with open('EventNames.cpp', 'w') as output_file: |
| def writeln(text): |
| output_file.write(text + '\n') |
| writeln('''/* |
| * Copyright (C) 2005-2024 Apple Inc. All rights reserved. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| * |
| */ |
| |
| #include "config.h" |
| #include "EventNames.h" |
| |
| namespace WebCore { |
| ''') |
| |
| # Generate static constexpr StaticStringImpl declarations |
| for name in sorted(event_names_input.keys()): |
| conditional = event_names_input[name].get('conditional', None) |
| if conditional: |
| writeln(f'#if {conditional}') |
| writeln(f'static constexpr StringImpl::StaticStringImpl {name}Data("{name}", StringImpl::StringAtom);') |
| if conditional: |
| writeln('#endif') |
| |
| writeln('') |
| |
| # Generate constructor using StaticStringImpl references |
| writeln('EventNames::EventNames()') |
| |
| delimiter = ':' |
| for name in sorted(event_names_input.keys()): |
| conditional = event_names_input[name].get('conditional', None) |
| if conditional: |
| writeln(f'#if {conditional}') |
| writeln(f' {delimiter} {name}Event({name}Data)') |
| delimiter = ',' |
| if conditional: |
| writeln('#endif') |
| |
| # m_typeInfoMap uses already-initialized member variables as keys |
| writeln(f' {delimiter} m_typeInfoMap({{') |
| for name in sorted(event_names_input.keys()): |
| entry = event_names_input[name] |
| conditional = entry.get('conditional', None) |
| if conditional: |
| writeln(f'#if {conditional}') |
| write(f' {{ \"{name}\"_s, {{ EventType::{name}, {{ ') |
| categories = entry.get('categories', []) |
| if categories: |
| for category in categories[:-1]: |
| write(f'EventCategory::{category}, ') |
| write(f'EventCategory::{categories[-1]} ') |
| write('}, ') |
| if entry.get('defaultEventHandler', False): |
| write('EventTypeInfo::DefaultEventHandler::Yes') |
| else: |
| write('EventTypeInfo::DefaultEventHandler::No') |
| writeln(' } },') |
| if conditional: |
| writeln('#endif') |
| writeln(' })') |
| writeln('{ }') |
| writeln('') |
| writeln(f'std::array<const AtomString, {len(event_names_input)}> EventNames::allEventNames() const') |
| writeln('{') |
| writeln(' return { {') |
| for name in sorted(event_names_input.keys()): |
| conditional = event_names_input[name].get('conditional', None) |
| if conditional: |
| writeln(f'#if {conditional}') |
| writeln(f' {name}Event,') |
| if conditional: |
| writeln(f'#endif') |
| writeln(''' } };''') |
| writeln('}') |
| writeln('') |
| writeln(f'WTF::HashSet<AtomString> EventNames::allEventHandlerNames() const') |
| writeln('{') |
| writeln(f' WTF::HashSet<AtomString> set;') |
| for name in sorted(event_names_input.keys()): |
| conditional = event_names_input[name].get('conditional', None) |
| if conditional: |
| writeln(f'#if {conditional}') |
| writeln(f' set.add("on{name.lower()}"_s);') |
| if conditional: |
| writeln(f'#endif') |
| writeln(' return set;') |
| writeln('}') |
| writeln('') |
| writeln(f'static constexpr std::array<const AtomString EventNames::*, {len(event_names_input)}> eventStringInEventNames {{') |
| for name in sorted(event_names_input.keys()): |
| entry = event_names_input[name] |
| conditional = entry.get('conditional', None) |
| writeln(f'#if {conditional}') if conditional else None |
| writeln(f' &EventNames::{name}Event,') |
| writeln(f'#endif') if conditional else None |
| writeln('};') |
| writeln(''' |
| const AtomString& EventNames::eventNameFromEventType(EventType type) const { |
| auto typeAsIndex = static_cast<size_t>(type) - 1; |
| return this->*(eventStringInEventNames[typeAsIndex]); |
| } |
| |
| } // namespace WebCore''') |
| |
| |
| if __name__ == '__main__': |
| main() |