143 lines
3.8 KiB
CMake
143 lines
3.8 KiB
CMake
# seeks the beginning of the enum while also keeping track of namespaces
|
|
macro(seek_enum_mode)
|
|
if(line MATCHES "^namespace ")
|
|
string(REGEX REPLACE "^namespace ([a-zA-Z0-9:_]+).*$" "\\1" tmp "${line}")
|
|
list(APPEND namespaces "${tmp}")
|
|
elseif(line MATCHES "^enum ")
|
|
if(NOT namespaces)
|
|
message(FATAL_ERROR "enum found outside of a namespace")
|
|
endif()
|
|
if(line MATCHES "^enum class ")
|
|
set(is_enum_class TRUE)
|
|
endif()
|
|
string(REGEX REPLACE "^enum (class )?([0-9a-zA-Z_]+).*$" "\\2" enum_name "${line}")
|
|
set(mode "read_values")
|
|
endif()
|
|
endmacro()
|
|
|
|
# scans the input for enum values
|
|
macro(read_values_mode)
|
|
if(line MATCHES "^}")
|
|
set(mode "generate")
|
|
elseif(line MATCHES "^[0-9a-zA-Z_]+")
|
|
string(REGEX REPLACE "^([0-9a-zA-Z_]+).*$" "\\1" tmp "${line}")
|
|
list(APPEND enum_values "${tmp}")
|
|
endif()
|
|
endmacro()
|
|
|
|
macro(write_enum_file)
|
|
if(is_enum_class)
|
|
set(label_prefix "${enum_name}::")
|
|
else()
|
|
set(label_prefix "")
|
|
endif()
|
|
string(REPLACE ";" "::" namespace_str "${namespaces}")
|
|
string(REPLACE "::" "/" namespace_path "${namespace_str}")
|
|
set(out "")
|
|
# File header and includes.
|
|
list(APPEND out
|
|
"#include \"caf/config.hpp\"\n"
|
|
"#include \"caf/string_view.hpp\"\n"
|
|
"\n"
|
|
"CAF_PUSH_DEPRECATED_WARNING\n"
|
|
"\n"
|
|
"#include \"${namespace_path}/${enum_name}.hpp\"\n"
|
|
"\n"
|
|
"#include <string>\n"
|
|
"\n"
|
|
"namespace ${namespace_str} {\n"
|
|
"\n")
|
|
# Generate to_string implementation.
|
|
list(APPEND out
|
|
"std::string to_string(${enum_name} x) {\n"
|
|
" switch (x) {\n"
|
|
" default:\n"
|
|
" return \"???\"\;\n")
|
|
foreach(label IN LISTS enum_values)
|
|
list(APPEND out
|
|
" case ${label_prefix}${label}:\n"
|
|
" return \"${namespace_str}::${enum_name}::${label}\"\;\n")
|
|
endforeach()
|
|
list(APPEND out
|
|
" }\n"
|
|
"}\n"
|
|
"\n")
|
|
# Generate from_string implementation.
|
|
list(APPEND out
|
|
"bool from_string(string_view in, ${enum_name}& out) {\n")
|
|
foreach(label IN LISTS enum_values)
|
|
list(APPEND out
|
|
" if (in == \"${namespace_str}::${enum_name}::${label}\") {\n"
|
|
" out = ${label_prefix}${label}\;\n"
|
|
" return true\;\n"
|
|
" }\n")
|
|
endforeach()
|
|
list(APPEND out
|
|
" return false\;\n"
|
|
"}\n"
|
|
"\n")
|
|
# Generate from_integer implementation.
|
|
list(APPEND out
|
|
"bool from_integer(std::underlying_type_t<${enum_name}> in,\n"
|
|
" ${enum_name}& out) {\n"
|
|
" auto result = static_cast<${enum_name}>(in)\;\n"
|
|
" switch (result) {\n"
|
|
" default:\n"
|
|
" return false\;\n")
|
|
foreach(label IN LISTS enum_values)
|
|
list(APPEND out
|
|
" case ${label_prefix}${label}:\n")
|
|
endforeach()
|
|
list(APPEND out
|
|
" out = result\;\n"
|
|
" return true\;\n"
|
|
" }\n"
|
|
"}\n"
|
|
"\n")
|
|
# File footer.
|
|
list(APPEND out
|
|
"} // namespace ${namespace_str}\n"
|
|
"\n")
|
|
file(WRITE "${OUTPUT_FILE}" ${out})
|
|
endmacro()
|
|
|
|
function(main)
|
|
set(namespaces "")
|
|
set(enum_name "")
|
|
set(enum_values "")
|
|
set(is_enum_class FALSE)
|
|
file(STRINGS "${INPUT_FILE}" lines)
|
|
set(mode "seek_enum")
|
|
foreach(line IN LISTS lines)
|
|
string(REGEX REPLACE "^(.+)(//.*)?" "\\1" line "${line}")
|
|
string(STRIP "${line}" line)
|
|
if(mode STREQUAL seek_enum)
|
|
seek_enum_mode()
|
|
elseif(mode STREQUAL read_values)
|
|
read_values_mode()
|
|
else()
|
|
# reached the end
|
|
if(NOT enum_name)
|
|
message(FATAL_ERROR "No enum found in input file")
|
|
endif()
|
|
if(NOT enum_values)
|
|
message(FATAL_ERROR "No enum values found for ${enum_name}")
|
|
endif()
|
|
write_enum_file()
|
|
return()
|
|
endif()
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# - check parameters and run ---------------------------------------------------
|
|
|
|
if(NOT INPUT_FILE)
|
|
message(FATAL_ERROR "Variable INPUT_FILE undefined")
|
|
endif()
|
|
|
|
if(NOT OUTPUT_FILE)
|
|
message(FATAL_ERROR "Variable OUTPUT_FILE undefined")
|
|
endif()
|
|
|
|
main()
|