Fawkes API  Fawkes Development Version
change_field.h
1 
2 /***************************************************************************
3  * change_field.h - Detect whether an update actually changes a field
4  ****************************************************************************/
5 
6 /* This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version. A runtime exception applies to
10  * this software (see LICENSE.GPL_WRE file mentioned below for details).
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Library General Public License for more details.
16  *
17  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
18  */
19 
20 #ifndef _INTERFACE_CHANGE_FIELD_H_
21 #define _INTERFACE_CHANGE_FIELD_H_
22 
23 #include <core/exceptions/software.h>
24 
25 #include <cstring>
26 #include <type_traits>
27 
28 namespace fawkes {
29 
30 /** Set a field and return whether it changed
31  * @param field The interface field to change
32  * @param value The new value
33  * @return Whether the new value is different from the old
34  */
35 template <class FieldT, class DataT>
36 bool
37 change_field(FieldT &field, const DataT &value)
38 {
39  bool rv = field != value;
40  field = value;
41  return rv;
42 }
43 
44 /** Set a string field and return whether it changed
45  * @param field The interface field to change
46  * @param value The new value
47  * @return Whether the new value is different from the old
48  */
49 template <class FieldT, std::size_t Size>
50 bool
51 change_field(FieldT (&field)[Size], const char *value)
52 {
53  bool change = ::strncmp(field, value, Size);
54  ::strncpy(field, value, Size - 1);
55  field[Size - 1] = 0;
56  return change;
57 }
58 
59 /** Set an array field and return whether it changed
60  * @param field The interface field to change
61  * @param value The new value
62  * @return Whether the new value is different from the old
63  */
64 template <class FieldT, std::size_t Size, class DataT>
65 typename std::enable_if<!std::is_same<FieldT, char>::value, bool>::type
66 change_field(FieldT (&field)[Size], const DataT *value)
67 {
68  bool change = ::memcmp(field, value, Size);
69  ::memcpy(field, value, sizeof(FieldT) * Size);
70  return change;
71 }
72 
73 /** Set an array field value at a certain index and return whether it changed
74  * @param field The interface field to change
75  * @param index Index into the array field
76  * @param value The new value
77  * @return Whether the new value is different from the old
78  */
79 template <class FieldT, std::size_t Size, class DataT>
80 bool
81 change_field(FieldT (&field)[Size], unsigned int index, const DataT &value)
82 {
83  if (index >= Size)
84  throw Exception("Index value %u is out of bounds (0..%u)", index, Size - 1);
85  bool change = field[index] != value;
86  field[index] = value;
87  return change;
88 }
89 
90 } // namespace fawkes
91 
92 #endif // _INTERFACE_CHANGE_FIELD_H_
Base class for exceptions in Fawkes.
Definition: exception.h:36
Fawkes library namespace.
bool change_field(FieldT &field, const DataT &value)
Set a field and return whether it changed.
Definition: change_field.h:37