Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / tt / lib / mp / mp_arg.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 //%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                  
24 //%%  (c) Copyright 1993, 1994 International Business Machines Corp.    
25 //%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                   
26 //%%  (c) Copyright 1993, 1994 Novell, Inc.                             
27 //%%  $XConsortium: mp_arg.C /main/3 1995/10/23 10:18:54 rswiston $                                                     
28 /*
29  *
30  * @(#)mp_arg.C 1.19 93/09/07
31  *
32  * Tool Talk Message Passer (MP) - mp_arg.C
33  *
34  * Copyright (c) 1990,1992 by Sun Microsystems, Inc.
35  *
36  * Implementation of the _Tt_arg & _Tt_arg_list classes representing
37  * arguments to a method or a procedure.
38  */
39 #include "mp/mp_global.h"
40 #include "mp/mp_arg.h"
41 #include <stdlib.h>
42 #include <string.h>
43 #include "util/tt_enumname.h"
44 #include "util/tt_iostream.h"
45 #include "util/tt_xdr_utils.h"
46 #include "util/tt_global_env.h"
47
48
49 /* 
50  * Construct a _Tt_arg with everything zeroed out
51  */
52 _Tt_arg::
53 _Tt_arg()
54 {
55         constructor_common();
56 }
57
58 /*
59  * Copy constructor for _Tt_args.
60  */
61 _Tt_arg::
62 _Tt_arg(const _Tt_arg &a)
63 {
64         _mode = a._mode;
65         _type = a._type;
66         _name = a._name;
67         _data_type = a._data_type;
68         _data_int = a._data_int;
69         _data_string = a._data_string;
70 }
71
72 /*
73  * Copy the _Tt_arg pointed to by a _Tt_arg_ptr.
74  */
75 _Tt_arg::
76 _Tt_arg(const _Tt_arg_ptr &p)
77 {
78         _mode = p->_mode;
79         _type = p->_type;
80         _name = p->_name;
81         _data_type = p->_data_type;
82         _data_int = p->_data_int;
83         _data_string = p->_data_string;
84 }
85
86 _Tt_arg::
87 _Tt_arg(const _Tt_string &t)
88 {
89         constructor_common();
90         _type = t;
91 }
92
93 /* 
94  * Constructs a _Tt_arg where the mode and type are known.
95  * No valid data is yet known.
96  * 
97  */
98 _Tt_arg::
99 _Tt_arg(Tt_mode m, _Tt_string &t)
100 {
101         constructor_common();
102         _mode = m;
103         _type = t;
104 }
105
106
107 _Tt_arg::
108 _Tt_arg(const char *t)
109 {
110         _Tt_string ts(t);
111         constructor_common();
112         _type = ts;
113 }
114
115 /* 
116  * Constructs a _Tt_arg where the mode and type are known.
117  * No valid data is yet known.
118  * 
119  */
120 _Tt_arg::
121 _Tt_arg(Tt_mode m, const char *t)
122 {
123         _Tt_string ts(t);
124         constructor_common();
125         _mode = m;
126         _type = ts;
127 }
128
129
130 /* 
131  * Destroys any memory associated with _Tt_arg
132  */
133 _Tt_arg::
134 ~_Tt_arg()
135 {
136 }
137
138
139 /* 
140  * Sets the data associated with this arg as an integer
141  */
142 Tt_status _Tt_arg::
143 set_data_int(int i)
144 {
145         _data_type = INT;
146         _data_int = i;
147         return TT_OK;
148 }
149
150
151 /* 
152  * Sets the data associated with this arg as a byte string
153  */ 
154 Tt_status _Tt_arg::
155 set_data_string(const _Tt_string &s)
156 {
157         _data_type = STRING;
158         _data_string = s;
159         return TT_OK;
160 }
161
162
163 /* 
164  * Obtain the data for this arg as an int.
165  * Return TT_ERR_NUM if the value is a string.
166  */
167 Tt_status _Tt_arg::
168 data_int(int &i) const
169 {
170         if (_data_type != INT) return TT_ERR_NUM;
171         i = _data_int;
172         return TT_OK;
173 }
174
175 /* 
176  * Obtain the data for this arg as a string.
177  * Return TT_ERR_POINTER if the value is an int.
178  */
179 Tt_status _Tt_arg::
180 data_string(_Tt_string &s) const
181 {
182         if (_data_type != STRING) return TT_ERR_POINTER;
183         s = _data_string;
184         return TT_OK;
185 }
186
187 /* 
188  * Prints out a _Tt_arg. Mainly used for debugging purposes only.
189  */
190 void _Tt_arg::
191 print(const _Tt_ostream &os) const
192 {
193         os << _tt_enumname(_mode) << " " << _type << ": ";
194
195         if (_name.len() > 0) {
196                 os << "<" << _name << ">\n";
197         } else if (_data_type==INT) {
198                 os << _data_int << "\n";
199         } else {
200                 _data_string.print(os, _Tt_string_user_width, 1);
201                 os << "\n";
202         }
203 }       
204
205
206 /* 
207  * XDR encodes and decodes a _Tt_arg object. Returns 1 if successful and
208  * 0 otherwise. 
209  */
210 bool_t _Tt_arg::
211 xdr(XDR *xdrs)
212 {
213         if (! xdr_int(xdrs, (int *)&_mode)) {
214                 return(0);
215         }
216         if (! _type.xdr(xdrs)) {
217                 return(0);
218         }
219         if (_tt_global->xdr_version() < TT_PUSH_ROTATE_XDR_VERSION) {
220                 //
221                 // Earlier versions of the XDR protocol included an
222                 // a never-used _Tt_string called _matched_type.
223                 //
224                 _Tt_string _matched_type;
225                 if (! _matched_type.xdr(xdrs)) {
226                         return(0);
227                 }
228         }
229         if (! _name.xdr(xdrs)) {
230                 return(0);
231         }
232         if (! xdr_int(xdrs, (int *)&_data_type)) {
233                 return(0);
234         }
235         if (_data_type==INT) {
236                 if (! xdr_int(xdrs, &_data_int)) {
237                         return(0);
238                 }
239         } else {                
240                 if (! _data_string.xdr(xdrs)) {
241                         return(0);
242                 }
243         }
244         return(1);
245 }
246
247 /*
248  * update_value is used when merging a reply with the original message.
249  * The value cells of this arg are updated with the value cells in the
250  * given arg.
251  */
252 Tt_status _Tt_arg::
253 update_value(const _Tt_arg &x)
254 {
255         _data_type = x._data_type;
256         _data_int = x._data_int;
257         _data_string = x._data_string;
258         return TT_OK;
259 }
260
261 /* 
262  * Wrapper whose only purpose is to invoke the xdr method on the given
263  * pointer. 
264  */
265 bool_t
266 tt_xdr_arg(XDR *xdrs, _Tt_arg_ptr *ptr)
267 {
268         return((*ptr)->xdr(xdrs));
269 }
270
271
272 /* 
273  * XDR encodes and decodes a list of _Tt_arg objects. p is assumed to
274  * point to the list on which to append/get the objects.
275  */
276 bool_t
277 tt_xdr_arg_list(XDR *xdrs, _Tt_arg_list_ptr *p)
278 {
279         return((*p).xdr(xdrs)); 
280 }
281
282
283 void 
284 _tt_arg_print(const _Tt_ostream &os, const _Tt_object *obj)
285 {
286         ((_Tt_arg *)obj)->print(os);
287 }
288
289 /*
290  * Common initialization code for _Tt_arg constructors.
291  */
292 void _Tt_arg::
293 constructor_common()
294 {
295         _mode = TT_MODE_UNDEFINED;
296         _type = (char *)0;
297         _name = (char *)0;
298         _data_type = UNSET;
299         _data_int = 0;
300         _data_string = (char *)0;
301 }       
302
303 /* 
304  * Returns non-zero score if \'this\', which must be a pattern arg, matches
305  * the given arg, which must be a message arg.  Matching is
306  * less restrictive than equality, since the following exceptions
307  * apply:
308  * 1\) If the pattern type is ALL, it matches any type in the message.
309  * 2\) If the message type is ALL, it matches any type in the pattern.
310  *    \[Somehow, the pattern type should get into the message, but
311  *     I don\'t know how yet.\]
312  * 3\) If the pattern value is not set, it matches any value in the
313  *    message.
314  * Although this method is only used in the server, it is too hard
315  * to figure out how to get messages and patterns un-XDRed in
316  * the server with args as a _Tt_s_arg instead of _Tt_arg.
317  */
318 int _Tt_arg::
319 match_score(const _Tt_arg &msg_arg, int &used_wildcard) const
320 {
321         // Comparing args works because XDR is defined as always
322         // padding with zeroes.
323
324         int score = 1; // wildcard match scores only 1
325         used_wildcard = 0;
326
327         // match modes
328         if (_mode == msg_arg.mode()) {
329                 score++;
330         } else if (_mode != TT_MODE_UNDEFINED) {
331                 return 0;
332         }
333
334         // match types
335         if (_type == msg_arg.type()) {
336                 // check equality first, in case both are "ALL"
337                 score++;
338         } else if (_type == "ALL") {
339                 used_wildcard = 1; // pattern ALL matches everything
340         } else if (msg_arg.type() == "ALL") {
341                 used_wildcard = 1; // message ALL matches everything
342         } else {
343                 return 0;       // types mismatched
344         }
345
346         // match values
347         switch (_data_type) {
348             case INT:
349             case STRING:
350             default:
351                 if (msg_arg.data_type() != _data_type) {
352                         return 0;
353                 }
354                 switch (_data_type) {
355                     case INT:
356                         if (msg_arg.data_int() != _data_int) {
357                                 return 0;
358                         }
359                         break;
360                     case STRING:
361                         if (msg_arg.data_string() != _data_string) {
362                                 return 0;
363                         }
364                         break;
365                     default:
366                         return 0;
367                 }
368                 score++;
369                 break;
370             case UNSET:
371                 if (msg_arg.data_type() != _data_type) {
372                         used_wildcard = 1;
373                 }
374                 break;
375         }
376
377         // everything matches
378         return score;
379 }
380
381 //
382 // Returns 1 if the typed values are equal, else 0.  Ignores mode and
383 // vtype.  Used by _Tt_pat_context::deleteValue().
384 //
385 int _Tt_arg::
386 operator==(const _Tt_arg &arg) const
387 {
388         if (_data_type != arg.data_type()) {
389                 return 0;
390         }
391         switch (_data_type) {
392             case INT:
393                 if (_data_int != arg.data_int()) {
394                         return 0;
395                 }
396                 break;
397             case STRING:
398                 if (_data_string != arg.data_string()) {
399                         return 0;
400                 }
401         }
402         return 1;
403 }