5 #ifndef _XDRC_TYPES_H_HEADER_INCLUDED_ 6 #define _XDRC_TYPES_H_HEADER_INCLUDED_ 1 30 uint32_t r {uint32_t(s)};
42 using std::runtime_error::runtime_error;
47 using xdr_runtime_error::xdr_runtime_error;
52 using xdr_runtime_error::xdr_runtime_error;
57 using xdr_runtime_error::xdr_runtime_error;
62 using xdr_runtime_error::xdr_runtime_error;
67 using xdr_runtime_error::xdr_runtime_error;
76 using std::logic_error::logic_error;
89 template<
typename T>
inline void 98 template<
typename T>
inline void 99 call_validate(
const T &, ...)
112 template<
typename T>
inline void 115 detail::call_validate(t, 0);
126 template<
typename T>
static void apply(Archive &ar, T &&t,
const char *) {
127 ar(std::forward<T>(t));
139 template<
typename Archive,
typename T>
inline void 140 archive(Archive &ar, T &&t,
const char *name =
nullptr)
148 static Constexpr
const bool valid =
false;
150 static Constexpr
const bool xdr_defined =
false;
152 static Constexpr
const bool is_bytes =
false;
154 static Constexpr
const bool is_struct =
false;
156 static Constexpr
const bool is_union =
false;
158 static Constexpr
const bool is_class =
false;
160 static Constexpr
const bool is_enum =
false;
162 static Constexpr
const bool is_container =
false;
164 static Constexpr
const bool is_numeric =
false;
166 static Constexpr
const bool has_fixed_size =
false;
178 template<
typename T>
struct has_fixed_size_t
179 : std::integral_constant<bool, xdr_traits<T>::has_fixed_size> {};
183 template<
typename T> std::size_t
192 static Constexpr
const bool valid =
true;
193 static Constexpr
const bool xdr_defined =
true;
194 static Constexpr
const bool is_bytes =
false;
195 static Constexpr
const bool is_class =
false;
196 static Constexpr
const bool is_enum =
false;
197 static Constexpr
const bool is_container =
false;
198 static Constexpr
const bool is_numeric =
false;
199 static Constexpr
const bool is_struct =
false;
200 static Constexpr
const bool is_union =
false;
201 static Constexpr
const bool has_fixed_size =
false;
214 template<
typename To,
typename From>
inline To
217 static_assert(
sizeof(To) ==
sizeof(From),
218 "xdr_reinterpret with different sized objects");
232 static Constexpr
const bool xdr_defined =
false;
233 static Constexpr
const bool is_numeric =
true;
234 static Constexpr
const bool has_fixed_size =
true;
235 static Constexpr
const std::size_t fixed_size =
sizeof(uint_type);
236 static Constexpr
const std::size_t serial_size(type) {
return fixed_size; }
237 static uint_type to_uint(type t) {
return t; }
238 static type from_uint(uint_type u) {
239 return xdr_reinterpret<type>(u);
245 using case_type = std::int32_t;
249 using case_type = std::uint32_t;
261 static_assert(
sizeof(type) ==
sizeof(uint_type),
262 "Cannot reinterpret between float and int of different size");
263 static Constexpr
const bool xdr_defined =
false;
264 static Constexpr
const bool is_numeric =
true;
265 static Constexpr
const bool has_fixed_size =
true;
266 static Constexpr
const std::size_t fixed_size =
sizeof(uint_type);
267 static Constexpr std::size_t serial_size(type) {
return fixed_size; }
269 static uint_type to_uint(type t) {
return xdr_reinterpret<uint_type>(t); }
270 static type from_uint(uint_type u) {
return xdr_reinterpret<type>(u); }
280 using case_type = std::int32_t;
281 static Constexpr
const bool xdr_defined =
false;
282 static Constexpr
const bool is_enum =
true;
283 static Constexpr
const bool is_numeric =
false;
284 static type from_uint(uint_type u) {
return u != 0; }
285 static Constexpr
const char *enum_name(uint32_t b) {
286 return b == 0 ?
"FALSE" : b == 1 ?
"TRUE" :
nullptr;
288 static const std::vector<int32_t> &enum_values() {
289 static const std::vector<int32_t> v = { 0, 1 };
303 static Constexpr
const uint32_t XDR_MAX_LEN = 0xfffffffc;
308 template<
typename T,
bool variable,
309 bool VFixed = detail::has_fixed_size_t<typename T::value_type>::value>
311 using value_type =
typename T::value_type;
312 static Constexpr
const bool is_container =
true;
314 static Constexpr
const bool variable_nelem = variable;
315 static Constexpr
const bool has_fixed_size =
false;
317 template<
typename Archive>
static void save(Archive &a,
const T &t) {
319 archive(a, size32(t.size()));
320 for (
const value_type &v : t)
323 template<
typename Archive>
static void load(Archive &a, T &t) {
332 n = size32(t.size());
333 for (uint32_t i = 0; i < n; ++i)
334 archive(a, t.extend_at(i));
336 static std::size_t serial_size(
const T &t) {
337 std::size_t s = variable ? 4 : 0;
338 for (
const value_type &v : t)
344 template<
typename T>
struct xdr_container_base<T, true, true>
345 : xdr_container_base<T, true, false> {
346 static std::size_t serial_size(
const T &t) {
351 template<
typename T>
struct xdr_container_base<T, false, true>
352 : xdr_container_base<T, false, false> {
353 static Constexpr
const bool has_fixed_size =
true;
354 static Constexpr
const std::size_t fixed_size =
356 static std::size_t serial_size(
const T &) {
return fixed_size; }
361 Constexpr no_clear_t() {}
363 Constexpr
const no_clear_t no_clear;
367 template<
typename T, u
int32_t N>
struct xarray 368 : std::array<T, size_t(N)> {
369 using array = std::array<T, size_t(N)>;
370 xarray() { array::fill(T{}); }
371 xarray(detail::no_clear_t) {}
375 static Constexpr
const std::size_t container_fixed_nelem = N;
376 static Constexpr
const std::size_t size() {
return N; }
378 static void check_size(uint32_t i) {
382 static void resize(uint32_t i) {
386 T &extend_at(uint32_t i) {
388 throw xdr_overflow(
"attempt to access invalid position in xdr::xarray");
393 template<
typename T, u
int32_t N>
395 : detail::xdr_container_base<xarray<T,N>, false> {};
399 :
xarray<std::uint8_t,N> {
401 using xarray::xarray;
403 opaque_array() : xarray(detail::no_clear) { std::memset(this->data(), 0, N); }
404 opaque_array(detail::no_clear_t) : xarray(detail::no_clear) {}
407 static Constexpr
const bool is_bytes =
true;
408 static Constexpr
const std::size_t has_fixed_size =
true;
409 static Constexpr
const std::size_t fixed_size =
410 (std::size_t(N) + std::size_t(3)) & ~std::size_t(3);
411 static std::size_t serial_size(
const opaque_array<N> &) {
return fixed_size; }
412 static Constexpr
const bool variable_nelem =
false;
419 template<
typename T, u
int32_t N = XDR_MAX_LEN>
421 using vector = std::vector<T>;
422 using vector::vector;
425 static Constexpr uint32_t max_size() {
return N; }
433 void append(
const T *elems, std::size_t n) {
434 check_size(this->size() + n);
435 this->insert(this->end(), elems, elems + n);
437 T &extend_at(uint32_t i) {
439 throw xdr_overflow(
"attempt to access invalid position in xdr::xvector");
440 if (i == this->size())
441 this->emplace_back();
444 void resize(uint32_t n) {
451 template<
typename T>
struct has_fixed_size_t<xvector<T>> : std::false_type {};
455 : detail::xdr_container_base<xvector<T,N>, true> {};
461 static Constexpr
const bool is_bytes =
true;
462 static Constexpr
const bool has_fixed_size =
false;;
463 static Constexpr std::size_t serial_size(
const opaque_vec<N> &a) {
464 return (std::size_t(a.size()) + std::size_t(7)) & ~std::size_t(3);
466 static Constexpr
const bool variable_nelem =
true;
473 template<u
int32_t N = XDR_MAX_LEN>
struct xstring : std::string {
474 using string = std::string;
477 static Constexpr uint32_t max_size() {
return N; }
498 template<
typename...Args>
xstring(Args&&...args)
499 : string(std::forward<Args>(args)...) {
validate(); }
502 char *data() {
return &(*this)[0]; }
505 #define ASSIGN_LIKE(method) \ 506 template<typename...Args> xstring &method(Args&&...args) { \ 507 string::method(std::forward<Args>(args)...); \ 511 ASSIGN_LIKE(
operator=)
512 ASSIGN_LIKE(
operator+=)
514 ASSIGN_LIKE(push_back)
521 void resize(size_type n) { check_size(n); string::resize(n); }
522 void resize(size_type n,
char ch) { check_size(n); string::resize(n, ch); }
526 static Constexpr
const bool is_bytes =
true;
527 static Constexpr
const bool has_fixed_size =
false;;
528 static Constexpr std::size_t serial_size(
const xstring<N> &a) {
529 return (std::size_t(a.size()) + std::size_t(7)) & ~std::size_t(3);
531 static Constexpr
const bool variable_nelem =
true;
536 template<
typename T>
struct pointer : std::unique_ptr<T> {
537 using value_type = T;
538 using std::unique_ptr<T>::unique_ptr;
539 using std::unique_ptr<T>::get;
541 pointer(
const pointer &p) : std::unique_ptr<T>(p ?
new T(*p) :
nullptr) {}
544 if (
const T *tp = up.get()) {
545 if (T *selfp = this->
get())
548 this->reset(
new T(*tp));
556 static void check_size(uint32_t n) {
560 uint32_t size()
const {
return *
this ? 1 : 0; }
561 T *begin() {
return get(); }
562 const T *begin()
const {
return get(); }
563 T *end() {
return begin() + size(); }
564 const T *end()
const {
return begin() + size(); }
565 T &extend_at(uint32_t i) {
567 throw xdr_overflow(
"attempt to access position > 0 in xdr::pointer");
572 void resize(uint32_t n) {
583 throw xdr_overflow(
"xdr::pointer::resize: valid sizes are 0 and 1");
588 this->reset(
new T{});
594 return (!a && !b) || (a && b && *a == *b);
600 return (!a && b) || (a && b && *a < *b);
618 : detail::xdr_container_base<pointer<T>, true, false> {};
629 template<
typename T,
typename F, F T::*Ptr>
struct field_ptr {
630 using class_type = T;
631 using field_type = F;
632 using value_type = F T::*;
634 static Constexpr value_type value() {
return Ptr; }
635 F &operator()(T &t)
const {
return t.*Ptr; }
636 const F &operator()(
const T &t)
const {
return t.*Ptr; }
637 F &operator()(T &&t)
const {
return std::move(t.*Ptr); }
644 template<
typename FP,
typename ...Fields>
646 static Constexpr
const bool has_fixed_size =
true;
647 static Constexpr
const std::size_t fixed_size =
650 static Constexpr std::size_t serial_size(
const typename FP::class_type &) {
655 template<
typename FP,
typename ...Fields>
657 static Constexpr
const bool has_fixed_size =
false;
658 static std::size_t serial_size(
const typename FP::class_type &t) {
668 static Constexpr
const bool is_class =
true;
669 static Constexpr
const bool is_struct =
true;
670 static Constexpr
const bool has_fixed_size =
true;
671 static Constexpr
const std::size_t fixed_size = 0;
672 template<
typename T>
static Constexpr std::size_t serial_size(
const T&) {
677 : std::conditional<(detail::has_fixed_size_t<typename FP::field_type>::value
678 && xdr_struct_base<Rest...>::has_fixed_size),
679 detail::xdr_struct_base_fs<FP, Rest...>,
680 detail::xdr_struct_base_vs<FP, Rest...>>::type {
681 using field_info = FP;
698 template<
typename T,
typename U>
struct cat_indices;
699 template<std::size_t...M, std::size_t...N>
700 struct cat_indices<indices<M...>, indices<N...>> {
701 using type = indices<M..., N...>;
704 template<std::
size_t N>
struct all_indices_helper {
705 using type =
typename cat_indices<
typename all_indices_helper<N-1>::type,
708 template<>
struct all_indices_helper<0> {
713 template<std::
size_t N>
using all_indices =
714 typename all_indices_helper<N>::type;
716 template<std::
size_t N,
typename T>
struct tuple_base;
718 template<std::
size_t N,
typename T>
struct tuple_base_fs;
719 template<std::size_t N,
typename...T>
721 using type = std::tuple<T...>;
722 using elem_type =
typename std::remove_cv<
723 typename std::remove_reference<
724 typename std::tuple_element<N-1, type>::type>::type>::type;
725 using next = tuple_base<N-1, type>;
726 static Constexpr
const bool xdr_defined =
false;
727 static Constexpr
const bool is_class =
true;
728 static Constexpr
const bool is_struct =
true;
729 static Constexpr
const bool has_fixed_size =
true;
730 static Constexpr
const std::uint32_t fixed_size =
732 static Constexpr std::size_t serial_size(
const type &) {
return fixed_size; }
735 template<std::
size_t N,
typename T>
struct tuple_base_vs;
736 template<std::size_t N,
typename...T>
738 using type = std::tuple<T...>;
739 using elem_type =
typename std::remove_cv<
740 typename std::remove_reference<
741 typename std::tuple_element<N-1, type>::type>::type>::type;
742 using next = tuple_base<N-1, type>;
743 static Constexpr
const bool xdr_defined =
false;
744 static Constexpr
const bool is_class =
true;
745 static Constexpr
const bool is_struct =
true;
746 static Constexpr
const bool has_fixed_size =
false;
747 static std::size_t serial_size(
const type &t) {
749 + next::serial_size(t));
753 template<
typename...T>
struct tuple_base<0, std::tuple<T...>>
755 using type = std::tuple<T...>;
756 static Constexpr
const bool xdr_defined =
false;
757 static Constexpr
const bool is_class =
true;
758 static Constexpr
const bool is_struct =
true;
759 static Constexpr
const bool has_fixed_size =
true;
760 static Constexpr
const std::size_t fixed_size = 0;
761 static Constexpr std::size_t serial_size(
const type &) {
return fixed_size; }
763 template<
typename Archive>
static void save(Archive &ar,
const type &obj) {}
764 template<
typename Archive>
static void load(Archive &ar, type &obj) {}
767 template<std::size_t N,
typename...T>
struct tuple_suffix_fixed_size {
768 using type = std::tuple<T...>;
769 using elem_type =
typename std::tuple_element<N-1, type>::type;
770 static Constexpr
const bool value =
772 && tuple_suffix_fixed_size<N-1, T...>::value;
774 template<
typename...T>
struct tuple_suffix_fixed_size<0, T...> {
775 static Constexpr
const bool value =
true;
778 template<std::size_t N,
typename...T>
struct tuple_base<N, std::tuple<T...>>
779 : std::conditional<tuple_suffix_fixed_size<N, T...>::value,
780 tuple_base_fs<N, std::tuple<T...>>,
781 tuple_base_vs<N, std::tuple<T...>>>::type {
782 using type = std::tuple<T...>;
785 static const char *name() {
return "<size unavailable on broken compiler>"; }
787 static const char *name() {
788 static std::string n =
"<" + std::to_string(N-1) +
">";
792 template<
typename Archive>
static void save(Archive &ar,
const type &obj) {
793 tuple_base<N-1, type>::save(ar, obj);
794 archive(ar, std::get<N-1>(obj), name());
796 template<
typename Archive>
static void load(Archive &ar, type &obj) {
797 tuple_base<N-1, type>::load(ar, obj);
798 archive(ar, std::get<N-1>(obj), name());
805 typename detail::all_indices<std::tuple_size<
806 typename std::remove_reference<T>::type>::value>;
809 : detail::tuple_base<sizeof...(T), std::tuple<T...>> {};
824 template<
typename T,
typename F>
inline F &
825 member(T &t, F T::*mp)
829 template<
typename T,
typename F>
inline const F &
830 member(
const T &t, F T::*mp)
834 template<
typename T,
typename F>
inline F &&
835 member(T &&t, F T::*mp)
837 return std::move(t.*mp);
843 template<
typename T,
typename F>
void operator()(F T::*mp, T &t)
const {
846 template<
typename T,
typename F,
typename TT>
void 847 operator()(F T::*mp, T &t, TT &&tt)
const {
848 new (&(t.*mp)) F (detail::member(std::forward<TT>(tt), mp));
859 template<
typename T,
typename F>
void 860 operator()(F T::*mp, T &t)
const { detail::member(t, mp).~F(); }
867 template<
typename T,
typename F,
typename TT>
void 868 operator()(F T::*mp, T &t, TT &&tt)
const {
869 detail::member(t, mp) = detail::member(std::forward<TT>(tt), mp);
878 template<
typename F,
typename T,
typename Archive>
void 879 operator()(F T::*mp, Archive &ar, T &t,
const char *name)
const {
880 archive(ar, detail::member(t, mp), name);
882 template<
typename F,
typename T,
typename Archive>
void 883 operator()(F T::*mp, Archive &ar,
const T &t,
const char *name)
const {
884 archive(ar, detail::member(t, mp), name);
892 template<
typename F,
typename T>
void 893 operator()(F T::*mp,
const T &t, std::size_t &size)
const {
907 template<
typename T,
typename F>
struct struct_equal_helper {
908 static bool equal(
const T &a,
const T &b) {
909 Constexpr
const typename F::field_info fi {};
910 if (!(fi(a) == fi(b)))
912 return struct_equal_helper<T, typename F::next_field>::equal(a, b);
915 template<
typename T>
struct struct_equal_helper<T, xdr_struct_base<>> {
916 static bool equal(
const T &,
const T &) {
return true; }
919 template<
typename T,
typename F>
struct struct_lt_helper {
920 static bool lt(
const T &a,
const T &b) {
921 Constexpr
const typename F::field_info fi {};
926 return struct_lt_helper<T, typename F::next_field>::lt(a, b);
929 template<
typename T>
struct struct_lt_helper<T, xdr_struct_base<>> {
930 static bool lt(
const T &,
const T &) {
return false; }
944 template<
typename T>
inline typename 949 return detail::struct_equal_helper<T, xdr_traits<T>>::equal(a, b);
952 template<
typename T>
inline typename 953 std::enable_if<xdr_traits<T>::is_struct && xdr_traits<T>::xdr_defined,
955 operator!=(
const T &a,
const T &b)
961 template<
typename T>
inline typename 962 std::enable_if<xdr_traits<T>::is_struct && xdr_traits<T>::xdr_defined,
966 return detail::struct_lt_helper<T, xdr_traits<T>>::lt(a, b);
969 template<
typename T>
inline typename 970 std::enable_if<xdr_traits<T>::is_struct && xdr_traits<T>::xdr_defined,
972 operator>(
const T &a,
const T &b)
977 template<
typename T>
inline typename 978 std::enable_if<xdr_traits<T>::is_struct && xdr_traits<T>::xdr_defined,
980 operator<=(
const T &a,
const T &b)
985 template<
typename T>
inline typename 986 std::enable_if<xdr_traits<T>::is_struct && xdr_traits<T>::xdr_defined,
988 operator>=(
const T &a,
const T &b)
994 struct union_field_equal_t {
995 Constexpr union_field_equal_t() {}
996 template<
typename T,
typename F>
997 void operator()(F T::*mp,
const T &a,
const T &b,
bool &out)
const {
998 out = a.*mp == b.*mp;
1001 Constexpr
const union_field_equal_t union_field_equal {};
1003 struct union_field_lt_t {
1004 Constexpr union_field_lt_t() {}
1005 template<
typename T,
typename F>
1006 void operator()(F T::*mp,
const T &a,
const T &b,
bool &out)
const {
1007 out = a.*mp < b.*mp;
1010 Constexpr
const union_field_lt_t union_field_lt {};
1015 template<
typename T>
inline typename 1016 std::enable_if<xdr_traits<T>::is_union,
bool>::type
1019 if (a._xdr_discriminant() == b._xdr_discriminant()) {
1021 a._xdr_with_mem_ptr(detail::union_field_equal,
1022 a._xdr_discriminant(), a, b, r);
1029 template<
typename T>
inline typename 1030 std::enable_if<xdr_traits<T>::is_union,
bool>::type
1033 if (a._xdr_discriminant() < b._xdr_discriminant())
1035 if (b._xdr_discriminant() < a._xdr_discriminant())
1039 a._xdr_with_mem_ptr(detail::union_field_lt,
1040 a._xdr_discriminant(), a, b, r);
1046 #endif // !_XDRC_TYPES_H_HEADER_INCLUDED_
std::size_t xdr_size(const T &t)
Return the marshaled size of an XDR data type.
Constexpr const field_constructor_t field_constructor
Passed to the auto-generated _xdr_with_mem_ptr static method to construct the active union field (or ...
std::tuple<> xdr_void
Placehoder type representing void values marshaled as 0 bytes.
This is used to apply an archive to a field.
Constexpr const field_size_t field_size
Passed to _xdr_with_mem_ptr to compute the size of the active union field.
Attempt to access wrong field of a union.
Attempt to exceed the bounds of a variable-length array or string.
Constexpr const field_destructor_t field_destructor
Passed to _xdr_with_mem_ptr to destroy the active union field.
Most of the xdrpp library is encapsulated in the xdr namespace.
XDR arrays are implemented using std::array as a supertype.
A string with a maximum length (returned by xstring::max_size()).
std::enable_if< xdr_traits< T >::is_struct &&xdr_traits< T >::xdr_defined, bool >::type operator==(const T &a, const T &b)
Equality for XDR structures.
Exception for use by xdr::xdr_validate.
Placeholder type used to contain a parameter pack of tuple indices, so as to unpack a tuple in functi...
Constexpr const field_assigner_t field_assigner
Passed to _xdr_with_mem_ptr to assign to the active union field.
Default traits for use as supertype of specializations of xdr_traits for integral types...
Default traits for use as supertype of specializations of xdr_traits for floating-point types...
Generic class of XDR unmarshaling errors.
Optional data (represented with pointer notation in XDR source).
XDR opaque is represented as std::uint8_t;.
Attempt to set invalid value for a union discriminant.
static void check_size(size_t n)
Check whether a size is in bounds.
Default xdr_traits values for actual XDR types, used as a supertype for most xdr::xdr_traits speciali...
std::enable_if< xdr_traits< T >::is_struct &&xdr_traits< T >::xdr_defined, bool >::type operator<(const T &a, const T &b)
Ordering of XDR structures. See note at xdr::operator==.
Low-level byteswap and miscellaneous OS compatibility routines.
Type-level representation of a pointer-to-member value.
Metadata for all marshalable XDR types.
A vector with a maximum size (returned by xvector::max_size()).
void validate(const T &t)
If this function template is specialized, it provides a means of placing extra restrictions on XDR da...
Message not multiple of 4 bytes, or cannot fully be parsed.
To xdr_reinterpret(From f)
A reinterpret-cast like function that works between types such as floating-point and integers of the ...
friend bool operator==(const pointer &a, const pointer &b)
Compare by value, rather than looking at the value of the pointer.
Padding bytes that should have contained zero don't.
void validate() const
Check that the string length is not greater than the maximum size.
static void check_size(size_t n)
Check whether a size is in bounds.
Constexpr const field_archiver_t field_archiver
Passed to _xdr_with_mem_ptr to archive the active union field.
typename detail::all_indices< std::tuple_size< typename std::remove_reference< T >::type >::value > all_indices_of
A type representing all the indices of a particuar tuple.