source: make_builder/enum_strings_builder/enum_strings.h @ 701:43444784a0ba

tip
Last change on this file since 701:43444784a0ba was 701:43444784a0ba, checked in by Tobias Föhst <tobias.foehst@…>, 17 months ago

Bugfix: throws exception for invalid enum values even in continuous enumerations

File size: 5.8 KB
Line 
1/**
2 * You received this file as part of an experimental
3 * build tool ('makebuilder') - originally developed for MCA2.
4 *
5 * Copyright (C) 2011 Max Reichardt,
6 *   Robotics Research Lab, University of Kaiserslautern
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 */
22//----------------------------------------------------------------------
23/*!\file    enum_strings.h
24 *
25 * \author  Max Reichardt
26 *
27 * \date    2011-08-24
28 *
29 * \brief Contains methods to retrieve auto-generated string constants
30 *        for enum types
31 */
32//----------------------------------------------------------------------
33
34#ifndef __make_builder__enum_strings_builder_h__
35#define __make_builder__enum_strings_builder_h__
36
37//----------------------------------------------------------------------
38// External includes (system with <>, local with "")
39//----------------------------------------------------------------------
40#include <vector>
41#include <string>
42#include <typeinfo>
43#include <stdexcept>
44
45//----------------------------------------------------------------------
46// Debugging
47//----------------------------------------------------------------------
48#include <cassert>
49
50//----------------------------------------------------------------------
51// Namespace declaration
52//----------------------------------------------------------------------
53namespace make_builder
54{
55
56//----------------------------------------------------------------------
57// Forward declarations / typedefs / enums
58//----------------------------------------------------------------------
59
60enum class tEnumStringsFormat
61{
62  NATURAL,
63  UPPER,
64  LOWER,
65  CAMEL,
66  DIMENSION
67};
68
69namespace internal
70{
71
72struct tEnumStrings
73{
74  const char * const *strings[static_cast<size_t>(tEnumStringsFormat::DIMENSION)];
75  const size_t size;
76  const void * const non_standard_values;
77};
78
79const tEnumStrings &GetEnumStrings(const char *type_name);
80
81template <typename TEnum>
82const tEnumStrings &GetEnumStrings()
83{
84  static const tEnumStrings &enum_strings(GetEnumStrings(typeid(TEnum).name()));
85  return enum_strings;
86}
87
88/*!
89 * (Typically, only used in generated code)
90 *
91 * Utility struct to intialize enum strings in static context
92 */
93struct tRegisterEnumStrings
94{
95  /*!
96   * \param type_name Normalized namespace and typename (normalized = without any template arguments)
97   * \param strings Enum strings to register (should be terminated with null pointer)
98   */
99  tRegisterEnumStrings(const char *type_name, const tEnumStrings &strings);
100};
101
102}
103
104//----------------------------------------------------------------------
105// Function declaration
106//----------------------------------------------------------------------
107
108template <typename TEnum>
109inline size_t GetEnumStringsDimension()
110{
111  return internal::GetEnumStrings<TEnum>().size;
112}
113
114/*!
115 * \return Enum strings for this enum data type
116 */
117template <typename TEnum>
118const char * const *GetEnumStrings(tEnumStringsFormat format = tEnumStringsFormat::NATURAL)
119{
120  assert(static_cast<size_t>(format) < static_cast<size_t>(tEnumStringsFormat::DIMENSION));
121  return internal::GetEnumStrings<TEnum>().strings[static_cast<size_t>(format)];
122}
123
124/*!
125 * \param value enum constant
126 * \return Enum string for this enum constant
127 */
128template <typename TEnum>
129inline const char *GetEnumString(TEnum value, tEnumStringsFormat format = tEnumStringsFormat::NATURAL)
130{
131  const internal::tEnumStrings& enum_strings = internal::GetEnumStrings<TEnum>();
132  if (enum_strings.non_standard_values)
133  {
134    const TEnum* values = static_cast<const TEnum*>(enum_strings.non_standard_values);
135    for (size_t i = 0; i < enum_strings.size; i++)
136    {
137      if (values[i] == value)
138      {
139        return enum_strings.strings[static_cast<size_t>(format)][i];
140      }
141    }
142  }
143  if (static_cast<size_t>(value) < enum_strings.size)
144  {
145    return enum_strings.strings[static_cast<size_t>(format)][static_cast<size_t>(value)];
146  }
147  throw std::runtime_error("Could not find enum string for value '" + std::to_string(static_cast<uint64_t>(value)) + "'!");
148}
149
150template <typename TEnum>
151inline TEnum GetEnumValueFromString(const std::string &string, tEnumStringsFormat expected_format = tEnumStringsFormat::DIMENSION)
152{
153  TEnum result;
154
155  size_t format_begin = static_cast<size_t>(expected_format);
156  size_t format_end = format_begin + 1;
157  if (expected_format == tEnumStringsFormat::DIMENSION)
158  {
159    format_begin = 0;
160    format_end = static_cast<size_t>(tEnumStringsFormat::DIMENSION);
161  }
162
163  for (size_t format = format_begin; format != format_end; ++format)
164  {
165    const internal::tEnumStrings& enum_strings = internal::GetEnumStrings<TEnum>();
166    const char * const *strings = enum_strings.strings[static_cast<size_t>(format)];
167    for (size_t i = 0; i < GetEnumStringsDimension<TEnum>(); ++i)
168    {
169      if (string == strings[i])
170      {
171        if (enum_strings.non_standard_values)
172        {
173          return static_cast<const TEnum*>(enum_strings.non_standard_values)[i];
174        }
175        return static_cast<TEnum>(i);
176      }
177    }
178  }
179
180  throw std::runtime_error("Could not find enum value for string '" + string + "'!");
181
182  return result;
183}
184
185//----------------------------------------------------------------------
186// End of namespace declaration
187//----------------------------------------------------------------------
188}
189
190#endif
Note: See TracBrowser for help on using the repository browser.