Branch data Line data Source code
1 : : /* Copyright 2006-2008 Savarese Software Research Corporation
2 : : *
3 : : * Licensed under the Apache License, Version 2.0 (the "License");
4 : : * you may not use this file except in compliance with the License.
5 : : * You may obtain a copy of the License at
6 : : *
7 : : * http://www.savarese.com/software/ApacheLicense-2.0
8 : : *
9 : : * Unless required by applicable law or agreed to in writing, software
10 : : * distributed under the License is distributed on an "AS IS" BASIS,
11 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : * See the License for the specific language governing permissions and
13 : : * limitations under the License.
14 : : */
15 : :
16 : : /**
17 : : * @file
18 : : * This header defines the WISP_STRUCT generative macro.
19 : : */
20 : :
21 : : #ifndef __SSRC_WISP_UTILITY_WISP_STRUCT_H
22 : : #define __SSRC_WISP_UTILITY_WISP_STRUCT_H
23 : :
24 : : #include <boost/preprocessor/punctuation/comma_if.hpp>
25 : : #include <boost/preprocessor/control/expr_iif.hpp>
26 : : #include <boost/preprocessor/comparison/equal.hpp>
27 : : #include <boost/preprocessor/comparison/less_equal.hpp>
28 : : #include <boost/preprocessor/comparison/greater_equal.hpp>
29 : : #include <boost/preprocessor/seq.hpp>
30 : : #include <boost/preprocessor/array/elem.hpp>
31 : : #include <boost/preprocessor/array/push_front.hpp>
32 : : #include <boost/preprocessor/stringize.hpp>
33 : : #include <boost/call_traits.hpp>
34 : :
35 : : #include <ssrc/wisp-packages.h>
36 : :
37 : : __BEGIN_NS_SSRC_WISP_UTILITY
38 : :
39 : : // This is a marker type, from which all WISP_STRUCT's are derived,
40 : : // to facilitate metaprogramming
41 : : // (e.g., std::is_base_of<wisp_struct, derived_type>).
42 : 22 : struct wisp_struct {
43 : : template<class Archive> void serialize(Archive & ar, const unsigned int) { }
44 : : };
45 : :
46 : : __END_NS_SSRC_WISP_UTILITY
47 : :
48 : : #define __WISP_STRUCT_MEMBER(r, data, arg) \
49 : : BOOST_PP_TUPLE_ELEM(2, 0, arg) BOOST_PP_TUPLE_ELEM(2, 1, arg);
50 : :
51 : : #define __WISP_STRUCT_DEFAULT_INIT_MEMBER(r, data, i, arg) \
52 : : BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 1, arg)()
53 : :
54 : : #define __WISP_STRUCT_INIT_MEMBER(r, data, i, arg) \
55 : : BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 1, arg)(BOOST_PP_TUPLE_ELEM(2, 1, arg))
56 : :
57 : : #define __WISP_STRUCT_PARAM(r, in_template, i, arg) \
58 : : BOOST_PP_COMMA_IF(i) BOOST_PP_EXPR_IIF(in_template, typename) boost::call_traits<BOOST_PP_TUPLE_ELEM(2, 0, arg)>::param_type BOOST_PP_TUPLE_ELEM(2, 1, arg)
59 : :
60 : : #define __WISP_STRUCT_PARAM_INIT(r, init, i, arg) \
61 : : BOOST_PP_COMMA_IF(i) BOOST_PP_EXPR_IIF(BOOST_PP_ARRAY_ELEM(0, init), typename) boost::call_traits<BOOST_PP_TUPLE_ELEM(2, 0, arg)>::param_type BOOST_PP_TUPLE_ELEM(2, 1, arg) BOOST_PP_EXPR_IIF(BOOST_PP_GREATER_EQUAL(i, BOOST_PP_ARRAY_ELEM(1, init)), = BOOST_PP_ARRAY_ELEM(BOOST_PP_SUB(BOOST_PP_ADD(i, 2), BOOST_PP_ARRAY_ELEM(1, init)), init))
62 : :
63 : : #define __WISP_STRUCT_SERIALIZE(r, data, arg) & BOOST_PP_TUPLE_ELEM(2, 1, arg)
64 : :
65 : : // Serialization
66 : : #define __WISP_STRUCT_SERIALIZE_MEMBERS(members) \
67 : : template<class Archive> \
68 : : void serialize(Archive & ar, const unsigned int) { \
69 : : ar BOOST_PP_SEQ_FOR_EACH(__WISP_STRUCT_SERIALIZE, _, members); \
70 : : } \
71 : :
72 : : // Equality
73 : : #define __WISP_STRUCT_EQOP_TEST(r, data, i, arg) \
74 : : BOOST_PP_EXPR_IF(i, &&) (o1.BOOST_PP_TUPLE_ELEM(2, 1, arg) == o2.BOOST_PP_TUPLE_ELEM(2, 1, arg))
75 : :
76 : : #define __WISP_STRUCT_EQOP(name, seq) \
77 : : friend bool operator==(const name & o1, const name & o2) { \
78 : : return (BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_EQOP_TEST, _, seq)); \
79 : : }
80 : :
81 : : // Member visitation. Visitor object must implement
82 : : // Visitor & operator(const char * const key, const V & value)
83 : : // or
84 : : // Visitor & operator(const std::string & key, const V & value)
85 : : // (possibly templatized on V) for each type to be visited.
86 : : // Non-const value arg versions can be implemented as well if the visitor
87 : : // wants to modify the members. Operators return *this to allow chaining.
88 : : #define __WISP_STRUCT_VISIT_MEMBERS(r, v, arg) \
89 : : (BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, arg)), BOOST_PP_TUPLE_ELEM(2, 1, arg))
90 : :
91 : : // Swig doesn't understand rvalue references
92 : : #ifndef SWIG
93 : : #define __WISP_STRUCT_VISIT(members) \
94 : : template<typename Visitor> \
95 : : void visit(Visitor && visitor) { \
96 : : visitor BOOST_PP_SEQ_FOR_EACH(__WISP_STRUCT_VISIT_MEMBERS, visitor, members); \
97 : : } \
98 : : template<typename Visitor> \
99 : : void visit(Visitor && visitor) const { \
100 : : visitor BOOST_PP_SEQ_FOR_EACH(__WISP_STRUCT_VISIT_MEMBERS, visitor, members); \
101 : : }
102 : : #else
103 : : #define __WISP_STRUCT_VISIT(members)
104 : : #endif
105 : :
106 : : // We exclude the struct name { } container for the benefit of client
107 : : // code that wants to define its own macros that add extra functionality
108 : : // to the generated structures.
109 : : #define __WISP_STRUCT(in_template, name, members) \
110 : : BOOST_PP_SEQ_FOR_EACH(__WISP_STRUCT_MEMBER, _, members) \
111 : : name() : \
112 : : BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_DEFAULT_INIT_MEMBER, _, members) { } \
113 : : explicit name(BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_PARAM, in_template, members)) : \
114 : : BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_INIT_MEMBER, _, members) { } \
115 : : __WISP_STRUCT_SERIALIZE_MEMBERS(members) \
116 : : __WISP_STRUCT_EQOP(name, members) \
117 : : __WISP_STRUCT_VISIT(members)
118 : :
119 : : #define __WISP_STRUCT_WITH_INIT(in_template, name, members, initializers) \
120 : : BOOST_PP_SEQ_FOR_EACH(__WISP_STRUCT_MEMBER, _, members) \
121 : : explicit name(BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_PARAM_INIT, BOOST_PP_ARRAY_PUSH_FRONT(BOOST_PP_ARRAY_PUSH_FRONT(initializers, BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(members), BOOST_PP_ARRAY_SIZE(initializers))), in_template), members)) : \
122 : : BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_INIT_MEMBER, _, members) { } \
123 : : __WISP_STRUCT_SERIALIZE_MEMBERS(members) \
124 : : __WISP_STRUCT_EQOP(name, members) \
125 : : __WISP_STRUCT_VISIT(members)
126 : :
127 : : #define WISP_STRUCT(name, members) \
128 : : struct name : public NS_SSRC_WISP_UTILITY::wisp_struct { __WISP_STRUCT(0, name, members) }
129 : :
130 : : #define WISP_STRUCT_T(name, members) \
131 : : struct name : public NS_SSRC_WISP_UTILITY::wisp_struct { __WISP_STRUCT(1, name, members) }
132 : :
133 : : #define WISP_STRUCT_WITH_INIT(name, members, initializers) \
134 : : struct name : public NS_SSRC_WISP_UTILITY::wisp_struct { __WISP_STRUCT_WITH_INIT(0, name, members, BOOST_PP_SEQ_TO_ARRAY(initializers)) }
135 : :
136 : : #define WISP_STRUCT_WITH_INIT_T(name, members, initializers) \
137 : : struct name : public NS_SSRC_WISP_UTILITY::wisp_struct { __WISP_STRUCT_WITH_INIT(1, name, members, BOOST_PP_SEQ_TO_ARRAY(initializers)) }
138 : :
139 : : #endif
|