should be it
This commit is contained in:
161
external/duckdb/scripts/generate_enums.py
vendored
Normal file
161
external/duckdb/scripts/generate_enums.py
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
|
||||
targets = [{'source': 'extension/json/include/', 'target': 'extension/json'}]
|
||||
|
||||
file_list = []
|
||||
for target in targets:
|
||||
source_base = os.path.sep.join(target['source'].split('/'))
|
||||
target_base = os.path.sep.join(target['target'].split('/'))
|
||||
for fname in os.listdir(source_base):
|
||||
if '_enums.json' not in fname:
|
||||
continue
|
||||
file_list.append(
|
||||
{
|
||||
'source': os.path.join(source_base, fname),
|
||||
'include_path': fname.replace('.json', '.hpp'),
|
||||
'target_hpp': os.path.join(source_base, fname.replace('.json', '.hpp')),
|
||||
'target_cpp': os.path.join(target_base, fname.replace('.json', '.cpp')),
|
||||
}
|
||||
)
|
||||
|
||||
header = '''//===----------------------------------------------------------------------===//
|
||||
// This file is automatically generated by scripts/generate_enums.py
|
||||
// Do not edit this file manually, your changes will be overwritten
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
${INCLUDE_LIST}
|
||||
namespace duckdb {
|
||||
'''
|
||||
|
||||
footer = '''
|
||||
} // namespace duckdb
|
||||
'''
|
||||
|
||||
include_base = '#include "${FILENAME}"\n'
|
||||
|
||||
enum_header = '\nenum class ${ENUM_NAME} : ${ENUM_TYPE} {\n'
|
||||
|
||||
enum_footer = '};'
|
||||
|
||||
enum_value = '\t${ENUM_MEMBER} = ${ENUM_VALUE},\n'
|
||||
|
||||
enum_util_header = '''
|
||||
template<>
|
||||
const char* EnumUtil::ToChars<${ENUM_NAME}>(${ENUM_NAME} value);
|
||||
|
||||
template<>
|
||||
${ENUM_NAME} EnumUtil::FromString<${ENUM_NAME}>(const char *value);
|
||||
'''
|
||||
|
||||
enum_util_conversion_begin = '''
|
||||
template<>
|
||||
const char* EnumUtil::ToChars<${ENUM_NAME}>(${ENUM_NAME} value) {
|
||||
switch(value) {
|
||||
'''
|
||||
|
||||
enum_util_switch = '\tcase ${ENUM_NAME}::${ENUM_MEMBER}:\n\t\treturn "${ENUM_MEMBER}";\n'
|
||||
|
||||
enum_util_conversion_end = ''' default:
|
||||
throw NotImplementedException(StringUtil::Format("Enum value of type ${ENUM_NAME}: '%d' not implemented", value));
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
from_string_begin = '''
|
||||
template<>
|
||||
${ENUM_NAME} EnumUtil::FromString<${ENUM_NAME}>(const char *value) {
|
||||
'''
|
||||
|
||||
from_string_comparison = ''' if (StringUtil::Equals(value, "${ENUM_MEMBER}")) {
|
||||
return ${ENUM_NAME}::${ENUM_MEMBER};
|
||||
}
|
||||
'''
|
||||
|
||||
from_string_end = ''' throw NotImplementedException(StringUtil::Format("Enum value of type ${ENUM_NAME}: '%s' not implemented", value));
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
class EnumMember:
|
||||
def __init__(self, entry, index):
|
||||
self.comment = None
|
||||
self.index = index
|
||||
if type(entry) == str:
|
||||
self.name = entry
|
||||
else:
|
||||
self.name = entry['name']
|
||||
if 'comment' in entry:
|
||||
self.comment = entry['comment']
|
||||
if 'index' in entry:
|
||||
self.index = int(entry['index'])
|
||||
|
||||
|
||||
class EnumClass:
|
||||
def __init__(self, entry):
|
||||
self.name = entry['name']
|
||||
self.type = 'uint8_t'
|
||||
self.values = []
|
||||
index = 0
|
||||
for value_entry in entry['values']:
|
||||
self.values.append(EnumMember(value_entry, index))
|
||||
index += 1
|
||||
|
||||
|
||||
for entry in file_list:
|
||||
source_path = entry['source']
|
||||
target_header = entry['target_hpp']
|
||||
target_source = entry['target_cpp']
|
||||
include_path = entry['include_path']
|
||||
with open(source_path, 'r') as f:
|
||||
json_data = json.load(f)
|
||||
|
||||
include_list = ['duckdb/common/constants.hpp', 'duckdb/common/enum_util.hpp']
|
||||
enums = []
|
||||
|
||||
for entry in json_data:
|
||||
if 'includes' in entry:
|
||||
include_list += entry['includes']
|
||||
enums.append(EnumClass(entry))
|
||||
|
||||
with open(target_header, 'w+') as f:
|
||||
include_text = '#pragma once\n\n'
|
||||
include_text += ''.join([include_base.replace('${FILENAME}', x) for x in include_list])
|
||||
f.write(header.replace('${INCLUDE_LIST}', include_text))
|
||||
|
||||
for enum in enums:
|
||||
f.write(enum_header.replace('${ENUM_NAME}', enum.name).replace('${ENUM_TYPE}', enum.type))
|
||||
for value in enum.values:
|
||||
if value.comment is not None:
|
||||
f.write('\t//! ' + value.comment + '\n')
|
||||
f.write(enum_value.replace('${ENUM_MEMBER}', value.name).replace('${ENUM_VALUE}', str(value.index)))
|
||||
|
||||
f.write(enum_footer)
|
||||
f.write('\n')
|
||||
|
||||
for enum in enums:
|
||||
f.write(enum_util_header.replace('${ENUM_NAME}', enum.name))
|
||||
|
||||
f.write(footer)
|
||||
|
||||
with open(target_source, 'w+') as f:
|
||||
source_include_list = [include_path, 'duckdb/common/string_util.hpp']
|
||||
f.write(
|
||||
header.replace(
|
||||
'${INCLUDE_LIST}', ''.join([include_base.replace('${FILENAME}', x) for x in source_include_list])
|
||||
)
|
||||
)
|
||||
|
||||
for enum in enums:
|
||||
f.write(enum_util_conversion_begin.replace('${ENUM_NAME}', enum.name))
|
||||
for value in enum.values:
|
||||
f.write(enum_util_switch.replace('${ENUM_MEMBER}', value.name).replace('${ENUM_NAME}', enum.name))
|
||||
|
||||
f.write(enum_util_conversion_end.replace('${ENUM_NAME}', enum.name))
|
||||
f.write(from_string_begin.replace('${ENUM_NAME}', enum.name))
|
||||
for value in enum.values:
|
||||
f.write(from_string_comparison.replace('${ENUM_MEMBER}', value.name).replace('${ENUM_NAME}', enum.name))
|
||||
|
||||
f.write(from_string_end.replace('${ENUM_NAME}', enum.name))
|
||||
f.write(footer)
|
||||
Reference in New Issue
Block a user