1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
# 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()
|