blob: 332b6a387c8a59c5eef52538dac8e4d3df4cb3ae [file]
#!/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()