File: caf-generate-enum-strings.cmake

package info (click to toggle)
actor-framework 0.18.7-1~exp1
  • links: PTS
  • area: main
  • in suites: experimental
  • size: 8,740 kB
  • sloc: cpp: 85,162; sh: 491; python: 187; makefile: 11
file content (142 lines) | stat: -rw-r--r-- 3,941 bytes parent folder | download
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()