162 lines
5.1 KiB
Python
162 lines
5.1 KiB
Python
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)
|