fix uint8_t writes over ascii protocol

%hhd seems to be unimplemented in some compilers. This caused `w axis0.requested_state 4` to return `not implemented` on fw v0.5.3.
This commit is contained in:
Samuel Sadok
2021-09-22 11:21:20 +02:00
parent 48148d8765
commit f451f3ff12
+24 -15
View File
@@ -131,42 +131,52 @@ struct format_traits_t;
template<> struct format_traits_t<long long> { using type = void;
static constexpr const char * fmt = "%lld";
static constexpr const char * fmtp = "%lld";
using scn_type = long long;
};
template<> struct format_traits_t<unsigned long long> { using type = void;
static constexpr const char * fmt = "%llu";
static constexpr const char * fmtp = "%llu";
using scn_type = unsigned long long;
};
template<> struct format_traits_t<long> { using type = void;
static constexpr const char * fmt = "%ld";
static constexpr const char * fmtp = "%ld";
using scn_type = long;
};
template<> struct format_traits_t<unsigned long> { using type = void;
static constexpr const char * fmt = "%lu";
static constexpr const char * fmtp = "%lu";
using scn_type = unsigned long;
};
template<> struct format_traits_t<int> { using type = void;
static constexpr const char * fmt = "%d";
static constexpr const char * fmtp = "%d";
using scn_type = int;
};
template<> struct format_traits_t<unsigned int> { using type = void;
static constexpr const char * fmt = "%ud";
static constexpr const char * fmtp = "%ud";
static constexpr const char * fmt = "%u";
static constexpr const char * fmtp = "%u";
using scn_type = unsigned int;
};
template<> struct format_traits_t<short> { using type = void;
static constexpr const char * fmt = "%hd";
static constexpr const char * fmtp = "%hd";
static constexpr const char * fmt = "%d";
static constexpr const char * fmtp = "%d";
using scn_type = int;
};
template<> struct format_traits_t<unsigned short> { using type = void;
static constexpr const char * fmt = "%hu";
static constexpr const char * fmtp = "%hu";
static constexpr const char * fmt = "%u";
static constexpr const char * fmtp = "%u";
using scn_type = unsigned int;
};
template<> struct format_traits_t<char> { using type = void;
static constexpr const char * fmt = "%hhd";
static constexpr const char * fmt = "%d";
static constexpr const char * fmtp = "%d";
using scn_type = int;
};
template<> struct format_traits_t<unsigned char> { using type = void;
static constexpr const char * fmt = "%hhu";
static constexpr const char * fmt = "%u";
static constexpr const char * fmtp = "%u";
using scn_type = unsigned int;
};
template<typename T, typename = typename format_traits_t<T>::type>
@@ -193,13 +203,12 @@ static bool to_string(const T& value, char * buffer, size_t length, ...) {
template<typename T, typename = typename format_traits_t<T>::type>
static bool from_string(const char * buffer, size_t length, T* property, int) {
// Note for T == uint8_t: Even though we supposedly use the correct format
// string sscanf treats our pointer as pointer-to-int instead of
// pointer-to-uint8_t. To avoid an unexpected memory access we first read
// into a union.
union { T t; int i; } val;
if (sscanf(buffer, format_traits_t<T>::fmt, &val.t) == 1) {
*property = val.t;
// sscanf doesn't work well with integers that are smaller than int, so we
// first scan into an appropriate int type and then convert it.
// (e.g. %hhu has been observed to not work on some compilers)
typename format_traits_t<T>::scn_type val;
if (sscanf(buffer, format_traits_t<T>::fmt, &val) == 1) {
*property = (T)val;
return true;
} else {
return false;