1# vim: set ts=4 sws=4 sw=4:
2
3# from utils import *
4from utils import _n, _ext, _n_item, get_namespace
5from parameter import *
6from resource_classes import _resource_classes
7from cppreply import CppReply
8from cppcookie import CppCookie
9
10_templates = {}
11
12_templates['void_request_function'] = \
13'''\
14template<typename Connection, typename ... Parameter>
15void
16%s_checked(Connection && c, Parameter && ... parameter)
17{
18  xpp::generic::check<Connection, xpp::%s::error::dispatcher>(
19      std::forward<Connection>(c),
20      %s_checked(
21          std::forward<Connection>(c),
22          std::forward<Parameter>(parameter) ...));
23}
24
25template<typename ... Parameter>
26void
27%s(Parameter && ... parameter)
28{
29  %s(std::forward<Parameter>(parameter) ...);
30}
31'''
32
33def _void_request_function(ns, name, c_name):
34    return _templates['void_request_function'] % \
35            ( name
36            , ns
37            , c_name
38            , name
39            , c_name
40            )
41
42_templates['reply_request_function'] = \
43'''\
44template<typename Connection, typename ... Parameter>
45reply::checked::%s<Connection>
46%s(Connection && c, Parameter && ... parameter)
47{
48  return reply::checked::%s<Connection>(
49      std::forward<Connection>(c), std::forward<Parameter>(parameter) ...);
50}
51
52template<typename Connection, typename ... Parameter>
53reply::unchecked::%s<Connection>
54%s_unchecked(Connection && c, Parameter && ... parameter)
55{
56  return reply::unchecked::%s<Connection>(
57      std::forward<Connection>(c), std::forward<Parameter>(parameter) ...);
58}
59'''
60
61def _reply_request_function(name):
62    return _templates['reply_request_function'] % \
63            ( name
64            , name
65            , name
66            , name
67            , name
68            , name)
69
70_templates['inline_reply_class'] = \
71'''\
72    template<typename ... Parameter>
73    auto
74    %s(Parameter && ... parameter) const
75    -> reply::checked::%s<Connection>
76    {
77      return xpp::%s::%s(
78          connection(),
79          %s\
80          std::forward<Parameter>(parameter) ...);
81    }
82
83    template<typename ... Parameter>
84    auto
85    %s_unchecked(Parameter && ... parameter) const
86    -> reply::unchecked::%s<Connection>
87    {
88      return xpp::%s::%s_unchecked(
89          connection(),
90          %s\
91          std::forward<Parameter>(parameter) ...);
92    }
93'''
94
95def _inline_reply_class(request_name, method_name, member, ns):
96    return _templates['inline_reply_class'] % \
97            ( method_name
98            , request_name
99            , ns
100            , request_name
101            , member
102            , method_name
103            , request_name
104            , ns
105            , request_name
106            , member
107            )
108
109_templates['inline_void_class'] = \
110'''\
111    template<typename ... Parameter>
112    void
113    %s_checked(Parameter && ... parameter) const
114    {
115      xpp::%s::%s_checked(connection(),
116                          %s\
117                          std::forward<Parameter>(parameter) ...);
118    }
119
120    template<typename ... Parameter>
121    void
122    %s(Parameter && ... parameter) const
123    {
124      xpp::%s::%s(connection(),
125                  %s\
126                  std::forward<Parameter>(parameter) ...);
127    }
128'''
129
130def _inline_void_class(request_name, method_name, member, ns):
131    return _templates['inline_void_class'] % \
132            ( method_name
133            , ns
134            , request_name
135            , member
136            , method_name
137            , ns
138            , request_name
139            , member
140            )
141
142_replace_special_classes = \
143        { "gcontext" : "gc" }
144
145def replace_class(method, class_name):
146    cn = _replace_special_classes.get(class_name, class_name)
147    return method.replace("_" + cn, "")
148
149class CppRequest(object):
150    def __init__(self, request, name, is_void, namespace, reply):
151        self.request = request
152        self.name = name
153        self.request_name = _ext(_n_item(self.request.name[-1]))
154        self.is_void = is_void
155        self.namespace = namespace
156        self.reply = reply
157        self.c_namespace = \
158            "" if namespace.header.lower() == "xproto" \
159            else get_namespace(namespace)
160        self.accessors = []
161        self.parameter_list = ParameterList()
162
163        self.c_name = "xcb" \
164            + (("_" + get_namespace(namespace)) if namespace.is_ext else "") \
165            + "_" + self.request_name
166
167    def add(self, param):
168        self.parameter_list.add(param)
169
170    def make_wrapped(self):
171        self.parameter_list.make_wrapped()
172
173    def make_class(self):
174        cppcookie = CppCookie(self.namespace, self.is_void, self.request.name, self.reply, self.parameter_list)
175
176        if self.is_void:
177            void_functions = cppcookie.make_void_functions()
178            if len(void_functions) > 0:
179                return void_functions
180            else:
181                return _void_request_function(get_namespace(self.namespace), self.request_name, self.c_name)
182
183        else:
184            cppreply = CppReply(self.namespace, self.request.name, cppcookie, self.reply, self.accessors, self.parameter_list)
185            return cppreply.make() + "\n\n" + _reply_request_function(self.request_name)
186
187    def make_object_class_inline(self, is_connection, class_name=""):
188        member = ""
189        method_name = self.name
190        if not is_connection:
191            member = "resource(),\n"
192            method_name = replace_class(method_name, class_name)
193
194        if self.is_void:
195            return _inline_void_class(self.request_name, method_name, member, get_namespace(self.namespace))
196        else:
197            return _inline_reply_class(self.request_name, method_name, member, get_namespace(self.namespace))
198