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