]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/cxx/lib/ipc/include/ipc_stream
update
[l4.git] / l4 / pkg / cxx / lib / ipc / include / ipc_stream
1 // vi:ft=cpp
2 /**
3  * \file
4  * \brief IPC stream
5  */
6 /*
7  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8  *               Alexander Warg <warg@os.inf.tu-dresden.de>,
9  *               Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
10  *     economic rights: Technische Universität Dresden (Germany)
11  *
12  * This file is part of TUD:OS and distributed under the terms of the
13  * GNU General Public License 2.
14  * Please see the COPYING-GPL-2 file for details.
15  *
16  * As a special exception, you may use this file as part of a free software
17  * library without restriction.  Specifically, if other files instantiate
18  * templates or use macros or inline functions from this file, or you compile
19  * this file and link it with other files to produce an executable, this
20  * file does not by itself cause the resulting executable to be covered by
21  * the GNU General Public License.  This exception does not however
22  * invalidate any other reasons why the executable file might be covered by
23  * the GNU General Public License.
24  */
25
26 #pragma once
27
28 #include <l4/sys/ipc.h>
29 #include <l4/sys/capability>
30 #include <l4/cxx/type_traits>
31
32 #define L4_CXX_IPC_BACKWARD_COMPAT 1
33
34 namespace L4 {
35
36 typedef int Opcode;
37
38 namespace Ipc {
39
40 class Ostream;
41 class Istream;
42
43 /**
44  * \brief Abstraction for inserting an array into an Ipc::Ostream.
45  * \ingroup ipc_fw
46  *
47  * An object of Buf_cp_out can be used to insert an array of arbitrary values,
48  * that can be inserted into an Ipc::Ostream individually.
49  * The array is therefore copied to the message buffer, in contrast to
50  * data handled with Msg_out_buffer or Msg_io_buffer.
51  *
52  * On insertion into the Ipc::Ostream exactly the given number of elements
53  * of type T are copied to the message buffer, this means the source buffer
54  * is no longer referenced after insertion into the stream.
55  *
56  * You should use buf_cp_out() to create instances of Buf_cp_out.
57  *
58  * The counterpart is either Buf_cp_in (buf_cp_in()) or Buf_in (buf_in()).
59  */
60 template< typename T >
61 class Buf_cp_out
62 {
63 public:
64   /**
65    * \brief Create a buffer object for the given array.
66    * \param v The pointer to the array with size elements of type T.
67    * \param size the number of elements in the array.
68    */
69   Buf_cp_out(T *v, unsigned long size) : _v(v), _s(size) {}
70
71   /**
72    * \brief Get the number of elements in the array.
73    * \note This function is usually used by the Ipc::Ostream itself.
74    */
75   unsigned long size() const { return _s; }
76
77   /**
78    * \brief Get the pointer to the array.
79    * \note This function is usually used by the Ipc::Ostream itself.
80    */
81   T *buf() const { return _v; }
82
83 private:
84   friend class Ostream;
85   T *_v;
86   unsigned long _s;
87 };
88
89 /**
90  * \brief Create an instance of Buf_cp_out for the given values.
91  * \ingroup ipc_fw
92  *
93  * This function makes it more convenient to insert arrays into an
94  * Ipc::Ostream (\see Buf_cp_out.)
95  *
96  * \param v Pointer to the array that shall be inserted into an Ipc::Ostream.
97  * \param size Number of elements in the array.
98  */
99 template< typename T >
100 Buf_cp_out<T> buf_cp_out(T *v, unsigned long size)
101 { return Buf_cp_out<T>(v,size); }
102
103
104 /**
105  * \brief Abstraction for extracting array from an Ipc::Istream.
106  * \ingroup ipc_fw
107  *
108  * An instance of Buf_cp_in can be used to extract an array from
109  * an Ipc::Istream. This is the counterpart to the Buf_cp_out abstraction.
110  * The data from the received message is thereby copied to the given buffer
111  * and size is set to the number of elements found in the stream.
112  * To avoid the copy operation Buf_in may be used instead.
113  *
114  * \see buf_cp_in(), Buf_in, buf_in(), Buf_cp_out, and buf_cp_out().
115  */
116 template< typename T >
117 class Buf_cp_in
118 {
119 public:
120   /**
121    * \brief Create a buffer for extracting an array from an Ipc::Istream.
122    * \param v The buffer for array (copy in).
123    * \param size Input: the number of elements the array can take at most<br>
124    *             Output: the number of elements found in the stream.
125    */
126   Buf_cp_in(T *v, unsigned long &size) : _v(v), _s(&size) {}
127
128   unsigned long &size() const { return *_s; }
129   T *buf() const { return _v; }
130 private:
131   friend class Istream;
132   T *_v;
133   unsigned long *_s;
134 };
135
136 /**
137  * \brief Create an Buf_cp_in for the given values.
138  * \ingroup ipc_fw
139  *
140  * This function makes it more convenient to extract arrays from an
141  * Ipc::Istream (\see Buf_cp_in.)
142  *
143  * \param v Pointer to the array that shall receive the values from the
144  *          Ipc::Istream.
145  * \param size Input: the number of elements the array can take at most<br>
146  *             Output: the number of elements found in the stream.
147  *
148  * \see buf_in() and buf_cp_out().
149  */
150 template< typename T >
151 Buf_cp_in<T> buf_cp_in(T *v, unsigned long &size)
152 { return Buf_cp_in<T>(v,size); }
153
154
155 /**
156  * \brief Pointer to an element of type T in an Ipc::Istream.
157  * \ingroup ipc_fw
158  *
159  * This wrapper can be used to extract an element of type T from an
160  * Ipc::Istream, whereas the data is not copied out, but a pointer into
161  * the message buffer itself is returned. With is mechanism it is possible
162  * to avoid an extra copy of large data structures from a received IPC
163  * message, instead the returned pointer gives direct access to the data
164  * in the message.
165  *
166  * See msg_ptr().
167  */
168 template< typename T >
169 class Msg_ptr
170 {
171 private:
172   T **_p;
173 public:
174   /**
175    * \brief Create a Msg_ptr object that set pointer p to point into the
176    *        message buffer.
177    * \param p The pointer that is adjusted to point into the message buffer.
178    */
179   explicit Msg_ptr(T *&p) : _p(&p) {}
180   void set(T *p) const { *_p = p; }
181 };
182
183 /**
184  * \brief Create an Msg_ptr to adjust the given pointer.
185  * \ingroup ipc_fw
186  *
187  * This function makes it more convenient to extract pointers to data in the
188  * message buffer itself from an Ipc::Istream.
189  * This may be used to avoid copy out of large data structures.
190  * (See Msg_ptr.)
191  */
192 template< typename T >
193 Msg_ptr<T> msg_ptr(T *&p)
194 { return Msg_ptr<T>(p); }
195
196
197 /**
198  * \brief Abstraction to extract an array from an Ipc::Istream.
199  * \ingroup ipc_fw
200  *
201  * This wrapper provides a possibility to extract an array from an
202  * Ipc::Istream, without extra copy overhead. In contrast to Buf_cp_in
203  * the data is not copied to a buffer, but a pointer to the array is returned.
204  *
205  * The mechanism is comparable to that of Msg_ptr, however it handles arrays
206  * inserted with Buf_cp_out.
207  *
208  * See buf_in(), Buf_cp_out, buf_cp_out(), Buf_cp_in, and buf_cp_in().
209  */
210 template< typename T >
211 class Buf_in
212 {
213 public:
214   /**
215    * \brief Create an Buf_in to adjust a pointer to the array and the size
216    *        of the array.
217    * \param v The pointer to adjust to the first element of the array.
218    * \param size The number of elements found in the stream.
219    */
220   Buf_in(T *&v, unsigned long &size) : _v(&v), _s(&size) {}
221
222   void set_size(unsigned long s) const { *_s = s; }
223   T *&buf() const { return *_v; }
224 private:
225   friend class Istream;
226   T **_v;
227   unsigned long *_s;
228 };
229
230 /**
231  * \brief Create an Buf_in for the given values.
232  * \ingroup ipc_fw
233  *
234  * This function makes it more convenient to extract arrays from an
235  * Ipc::Istream (See Buf_in.)
236  *
237  * \param v Output: pointer to the array within the Ipc::Istream.
238  * \param size Output: the number of elements found in the stream.
239  *
240  * See buf_cp_in() and buf_cp_out().
241  */
242 template< typename T >
243 Buf_in<T> buf_in(T *&v, unsigned long &size)
244 { return Buf_in<T>(v, size); }
245
246
247
248 /**
249  * \brief A receive item for receiving a single capability.
250  *
251  * This class is the main abstraction for receiving capabilities
252  * via Ipc::Istream. To receive a capability an instance of Small_buf
253  * that refers to an empty capability slot must be inserted into the
254  * Ipc::Istream before the receive operation.
255  */
256 class Small_buf
257 {
258 public:
259   explicit Small_buf(L4::Cap<L4::Kobject> cap, unsigned long flags = 0)
260   : _data(cap.cap() | L4_RCV_ITEM_SINGLE_CAP | flags) {}
261
262   explicit Small_buf(l4_cap_idx_t idx, unsigned long flags = 0)
263   : _data(idx | L4_RCV_ITEM_SINGLE_CAP | flags) {}
264 private:
265   l4_umword_t _data;
266 };
267
268 class Snd_item
269 {
270 public:
271   Snd_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
272
273 protected:
274   l4_umword_t _base;
275   l4_umword_t _data;
276 };
277
278 class Buf_item
279 {
280 public:
281   Buf_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
282
283 protected:
284   l4_umword_t _base;
285   l4_umword_t _data;
286 };
287
288 template< typename T >
289 class Gen_fpage : public T
290 {
291 public:
292   enum Type
293   {
294     Special = L4_FPAGE_SPECIAL << 4,
295     Memory  = L4_FPAGE_MEMORY << 4,
296     Io      = L4_FPAGE_IO << 4,
297     Obj     = L4_FPAGE_OBJ << 4
298   };
299
300   enum Map_type
301   {
302     Map   = L4_MAP_ITEM_MAP,
303     Grant = L4_MAP_ITEM_GRANT,
304   };
305
306   enum Cacheopt
307   {
308     None     = 0,
309     Cached   = L4_FPAGE_CACHEABLE << 4,
310     Buffered = L4_FPAGE_BUFFERABLE << 4,
311     Uncached = L4_FPAGE_UNCACHEABLE << 4
312   };
313
314   enum Continue
315   {
316     Single   = 0,
317     Last     = 0,
318     More     = L4_ITEM_CONT,
319     Compound = L4_ITEM_CONT,
320   };
321
322 private:
323   Gen_fpage(Type type, l4_addr_t base, int order,
324             unsigned char rights,
325             l4_addr_t snd_base,
326             Map_type map_type,
327             Cacheopt cache, Continue cont)
328   : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache)
329       | l4_umword_t(cont),
330       base | l4_umword_t(type) | rights | (l4_umword_t(order) << 6))
331   {}
332
333 public:
334   Gen_fpage() : T(0, 0) {}
335   Gen_fpage(l4_fpage_t const &fp, l4_addr_t snd_base = 0,
336             Map_type map_type = Map,
337             Cacheopt cache = None, Continue cont = Last)
338   : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache)
339     | l4_umword_t(cont),
340     fp.raw)
341   {}
342
343   Gen_fpage(L4::Cap<void> cap, unsigned rights)
344   : T(L4_ITEM_MAP | Map | (rights & 0xf0), cap.fpage(rights).raw)
345   {}
346
347   static Gen_fpage<T> obj(l4_addr_t base, int order,
348                           unsigned char rights,
349                           l4_addr_t snd_base = 0,
350                           Map_type map_type = Map,
351                           Continue cont = Last)
352   { return Gen_fpage<T>(Obj, base << 12, order, rights, snd_base, map_type, None, cont); }
353   static Gen_fpage<T> mem(l4_addr_t base, int order,
354                           unsigned char rights,
355                           l4_addr_t snd_base = 0,
356                           Map_type map_type = Map,
357                           Cacheopt cache = None, Continue cont = Last)
358   { return Gen_fpage<T>(Memory, base, order, rights, snd_base,
359                         map_type, cache, cont); }
360   static Gen_fpage<T> io(l4_addr_t base, int order,
361                           unsigned char rights,
362                           l4_addr_t snd_base = 0,
363                           Map_type map_type = Map,
364                           Continue cont = Last)
365     { return Gen_fpage<T>(Io, base << 12, order, rights, snd_base, map_type, None, cont); }
366
367   unsigned order() const { return (T::_data >> 6) & 0x3f; }
368   unsigned snd_order() const { return (T::_data >> 6) & 0x3f; }
369   unsigned rcv_order() const { return (T::_base >> 6) & 0x3f; }
370   l4_addr_t base() const { return T::_data & (~0UL << 12); }
371   l4_addr_t snd_base() const { return T::_base & (~0UL << 10); }
372   void snd_base(l4_addr_t b) { T::_base = (T::_base & ~(~0UL << 10)) | (b & (~0UL << 10)); }
373
374   bool is_valid() const { return T::_base & L4_ITEM_MAP; }
375   // A cap has been mapped
376   bool cap_received() const { return (T::_base & 0x3e) == 0x38; }
377   // the label out of an IPC gate has been received, L4_RCV_ITEM_LOCAL_ID
378   // must be specified, and the IPC gate must be local to the receiver
379   // (i.e., the target thread of the IPC gate is in the same task as the
380   // receiving thread)
381   bool id_received() const { return (T::_base & 0x3e) == 0x3c; }
382   // Sender and receiver are in the same task, set only iff
383   // L4_RCV_ITEM_LOCAL_ID has been specified by the receiver, the value
384   // delivered is the cap-index (in the task)
385   bool local_id_received() const { return (T::_base & 0x3e) == 0x3e; }
386   l4_umword_t data() const { return T::_data; }
387   l4_umword_t base_x() const { return T::_base; }
388 };
389
390
391 typedef Gen_fpage<Snd_item> Snd_fpage;
392 typedef Gen_fpage<Buf_item> Rcv_fpage;
393
394 #ifdef L4_CXX_IPC_SUPPORT_STRINGS
395 template <typename T, typename B>
396 class Gen_string : public T
397 {
398 public:
399   Gen_string() : T(0,0) {}
400   Gen_string(B buf, unsigned long size)
401   : T(size << 10, l4_umword_t(buf))
402   {}
403
404   unsigned long len() const { return T::_base >> 10; }
405 };
406
407 typedef Gen_string<Snd_item, void const *> Snd_string;
408 typedef Gen_string<Buf_item, void *> Rcv_string;
409 #endif
410
411
412 template< typename T, template <typename X> class B > struct Generic_va_type : public B<T>
413 {
414   enum { Id = B<T>::Id };
415   typedef B<T> ID;
416   typedef T const &Ret_value;
417   typedef T Value;
418
419   static Ret_value value(void const *d)
420   { return *reinterpret_cast<Value const *>(d); }
421
422   static void const *addr_of(Value const &v) { return &v; }
423
424   static unsigned size(void const *) { return sizeof(T); }
425
426   static L4_varg_type unsigned_id() { return (L4_varg_type)(Id & ~L4_VARG_TYPE_SIGN); }
427   static L4_varg_type signed_id() { return (L4_varg_type)(Id | L4_VARG_TYPE_SIGN); }
428   static L4_varg_type id() { return (L4_varg_type)Id; }
429 };
430
431 template< typename T > struct Va_type_id;
432 template<> struct Va_type_id<l4_umword_t>  { enum { Id = L4_VARG_TYPE_UMWORD }; };
433 template<> struct Va_type_id<l4_mword_t>   { enum { Id = L4_VARG_TYPE_MWORD }; };
434 template<> struct Va_type_id<l4_fpage_t>   { enum { Id = L4_VARG_TYPE_FPAGE }; };
435 template<> struct Va_type_id<void>         { enum { Id = L4_VARG_TYPE_NIL }; };
436 template<> struct Va_type_id<char const *> { enum { Id = L4_VARG_TYPE_STRING }; };
437
438 template< typename T > struct Va_type;
439
440 template<> struct Va_type<l4_umword_t> : public Generic_va_type<l4_umword_t, Va_type_id> {};
441 template<> struct Va_type<l4_mword_t> : public Generic_va_type<l4_mword_t, Va_type_id> {};
442 template<> struct Va_type<l4_fpage_t> : public Generic_va_type<l4_fpage_t, Va_type_id> {};
443
444 template<> struct Va_type<void>
445 {
446   typedef void Ret_value;
447   typedef void Value;
448
449   static void const *addr_of(void) { return 0; }
450
451   static void value(void const *) {}
452   static L4_varg_type id() { return L4_VARG_TYPE_NIL; }
453   static unsigned size(void const *) { return 0; }
454 };
455
456 template<> struct Va_type<char const *>
457 {
458   typedef char const *Ret_value;
459   typedef char const *Value;
460
461   static void const *addr_of(Value v) { return v; }
462
463   static L4_varg_type id() { return L4_VARG_TYPE_STRING; }
464   static unsigned size(void const *s)
465   {
466     char const *_s = reinterpret_cast<char const *>(s);
467     int l = 1;
468     while (*_s)
469       {
470         ++_s; ++l;
471       }
472     return l;
473   }
474
475   static Ret_value value(void const *d) { return (char const *)d; }
476 };
477
478
479 class Varg
480 {
481 private:
482   l4_umword_t _tag;
483   char const *_d;
484
485 public:
486
487   typedef l4_umword_t Tag;
488
489   L4_varg_type type() const { return (L4_varg_type)(_tag & 0xff); }
490   int length() const { return _tag >> 16; }
491
492   void tag(Tag tag) { _tag = tag; }
493   Tag tag() const { return _tag; }
494   void data(char const *d) { _d = d; }
495
496   char const *data() const { return _d; }
497   char const *&data() { return _d; }
498
499   Varg() : _tag(0), _d(0) {}
500
501   Varg(L4_varg_type t, void const  *v, int len)
502   : _tag(t | ((l4_mword_t)len << 16)), _d((char const *)v)
503   {}
504
505   template< typename V >
506   typename Va_type<V>::Ret_value value() const
507   { return Va_type<V>::value(_d); }
508
509
510   template< typename T >
511   bool is_of() const { return Va_type<T>::id() == type(); }
512
513   bool is_nil() const { return is_of<void>(); }
514
515   bool is_of_int() const
516   { return (type() & ~L4_VARG_TYPE_SIGN) == L4_VARG_TYPE_UMWORD; }
517
518   template< typename T >
519   bool get_value(typename Va_type<T>::Value *v) const
520   {
521     if (!is_of<T>())
522       return false;
523
524     *v = Va_type<T>::value(_d);
525     return true;
526   }
527
528   template< typename T >
529   void set_value(void const *d)
530   {
531     typedef Va_type<T> Vt;
532     _tag = Vt::id() | (Vt::size(d) << 16);
533     _d = (char const *)d;
534   }
535
536 };
537
538 template<typename T>
539 class Varg_t : public Varg
540 {
541 public:
542   typedef typename Va_type<T>::Value Value;
543   explicit Varg_t(Value v) : Varg()
544   { _data = v; set_value<T>(Va_type<T>::addr_of(_data)); }
545
546 private:
547   Value _data;
548 };
549
550 namespace Utcb_stream_check
551 {
552   static bool check_utcb_data_offset(unsigned sz)
553   { return sz > sizeof(l4_umword_t) * L4_UTCB_GENERIC_DATA_SIZE; }
554 }
555
556
557 /**
558  * \brief Input stream for IPC unmarshalling.
559  * \ingroup ipc_fw
560  *
561  * Ipc::Istream is part of the dynamic IPC marshalling infrastructure, as well
562  * as Ipc::Ostream and Ipc::Iostream.
563  *
564  * Ipc::Istream is an input stream supporting extraction of values from an
565  * IPC message buffer. A received IPC message can be unmarshalled using the
566  * usual extraction operator (>>).
567  *
568  * There exist some special wrapper classes to extract arrays (see
569  * Ipc_buf_cp_in and Ipc_buf_in) and indirect strings (see Msg_in_buffer and
570  * Msg_io_buffer).
571  */
572 class Istream
573 {
574 public:
575   /**
576    * \brief Create an input stream for the given message buffer.
577    *
578    * The given message buffer is used for IPC operations wait()/receive()
579    * and received data can be extracted using the >> operator afterwards.
580    * In the case of indirect message parts a buffer of type Msg_in_buffer
581    * must be inserted into the stream before the IPC operation and contains
582    * received data afterwards.
583    *
584    * \param msg The message buffer to receive IPC messages.
585    */
586   Istream(l4_utcb_t *utcb)
587   : _tag(), _utcb(utcb),
588     _current_msg(reinterpret_cast<char*>(l4_utcb_mr_u(utcb)->mr)),
589     _pos(0), _current_buf(0)
590   {}
591
592   /**
593    * \brief Reset the stream to empty, and ready for receive()/wait().
594    * The stream is reset to the same state as on its creation.
595    */
596   void reset()
597   {
598     _pos = 0;
599     _current_buf = 0;
600     _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
601   }
602
603   /**
604    * \brief Check whether a value of type T can be obtained from the stream.
605    */
606   template< typename T >
607   bool has_more()
608   {
609     unsigned apos = cxx::Type_traits<T>::align(_pos);
610     return apos + sizeof(T) <= _tag.words() * sizeof(l4_umword_t);
611   }
612
613   /**
614    * \name Get/Put Functions.
615    * These functions are basically used to implement the extraction operators
616    * (>>) and should not be called directly.
617    *
618    * See \link ipc_stream IPC stream operators \endlink.
619    */
620   //@{
621
622   /**
623    * \brief Copy out an array of type \a T with \a size elements.
624    *
625    * \param buf Pointer to a buffer for size elements of type T.
626    * \param size number of elements of type T to copy out.
627    *
628    * See \link ipc_stream IPC stream operators \endlink.
629    */
630   template< typename T >
631   void get(T *buf, unsigned long size)
632   {
633     size *= sizeof(T);
634     _pos = cxx::Type_traits<T>::align(_pos);
635     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
636       return;
637
638     __builtin_memcpy(buf, _current_msg + _pos, size);
639     _pos += size;
640   }
641
642
643   /**
644    * \brief Skip size elements of type T in the stream.
645    * \param size number of elements to skip.
646    */
647   template< typename T >
648   void skip(unsigned long size)
649   {
650     size *= sizeof(T);
651     _pos = cxx::Type_traits<T>::align(_pos);
652     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
653       return;
654     _pos += size;
655   }
656
657   /**
658    * \brief Read one size elements of type T from the stream and return
659    *        a pointer.
660    *
661    * In contrast to a normal get, this version does actually not copy the data
662    * but returns a pointer to the data.
663    *
664    * \param buf a Msg_ptr that is actually set to point to the element in the
665    *            stream.
666    * \param size number of elements to extract (default is 1).
667    *
668    * See \link ipc_stream IPC stream operators \endlink.
669    */
670   template< typename T >
671   void get(Msg_ptr<T> const &buf, unsigned long size = 1)
672   {
673     size *= sizeof(T);
674     _pos = cxx::Type_traits<T>::align(_pos);
675     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
676       return;
677
678     buf.set(reinterpret_cast<T*>(_current_msg + _pos));
679     _pos += size;
680   }
681
682
683   /**
684    * \brief Extract a single element of type T from the stream.
685    * \param v Output: the element.
686    *
687    * See \link ipc_stream IPC stream operators \endlink.
688    */
689   template< typename T >
690   void get(T &v)
691   {
692     _pos = cxx::Type_traits<T>::align(_pos);
693     if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
694       {
695         v = T();
696         return;
697       }
698     v = *(reinterpret_cast<T*>(_current_msg + _pos));
699     _pos += sizeof(T);
700   }
701
702
703   int get(Ipc::Varg *va)
704   {
705     Ipc::Varg::Tag t;
706     if (!has_more<Ipc::Varg::Tag>())
707       {
708         va->tag(0);
709         return 0;
710       }
711     get(t);
712     va->tag(t);
713     get(msg_ptr(va->data()), va->length());
714
715     return 0;
716   }
717
718   /**
719    * \brief Get the message tag of a received IPC.
720    * \return The L4 message tag for the received IPC.
721    *
722    * This is in particular useful for handling page faults or exceptions.
723    *
724    * See \link ipc_stream IPC stream operators \endlink.
725    */
726   l4_msgtag_t tag() const { return _tag; }
727
728
729   /**
730    * \brief Get the message tag of a received IPC.
731    * \return A reference to the L4 message tag for the received IPC.
732    *
733    * This is in particular useful for handling page faults or exceptions.
734    *
735    * See \link ipc_stream IPC stream operators \endlink.
736    */
737   l4_msgtag_t &tag() { return _tag; }
738
739   //@}
740
741   /**
742    * \internal
743    * \brief Put a receive item into the stream's buffer registers.
744    */
745   inline bool put(Buf_item const &);
746
747   /**
748    * \internal
749    * \brief Put a small receive item into the stream's buffer registers.
750    */
751   inline bool put(Small_buf const &);
752
753
754   /**
755    * \name IPC operations.
756    */
757   //@{
758
759   /**
760    * \brief Wait for an incoming message from any sender.
761    * \param src contains the sender after a successful IPC operation.
762    * \return The IPC result dope (l4_msgtag_t).
763    *
764    * This wait is actually known as 'open wait'.
765    */
766   inline l4_msgtag_t wait(l4_umword_t *src)
767   { return wait(src, L4_IPC_NEVER); }
768
769   /**
770    * \brief Wait for an incoming message from any sender.
771    * \param src contains the sender after a successful IPC operation.
772    * \param timeout Timeout used for IPC.
773    * \return The IPC result dope (l4_msgtag_t).
774    *
775    * This wait is actually known as 'open wait'.
776    */
777   inline l4_msgtag_t wait(l4_umword_t *src, l4_timeout_t timeout);
778
779   /**
780    * \brief Wait for a message from the specified sender.
781    * \param src The sender id to receive from.
782    * \return The IPC  result dope (l4_msgtag_t).
783    *
784    * This is commonly known as 'closed wait'.
785    */
786   inline l4_msgtag_t receive(l4_cap_idx_t src)
787   { return receive(src, L4_IPC_NEVER); }
788   inline l4_msgtag_t receive(l4_cap_idx_t src, l4_timeout_t timeout);
789
790   //@}
791
792   /**
793    * \brief Return utcb pointer.
794    */
795   inline l4_utcb_t *utcb() const { return _utcb; }
796
797 protected:
798   l4_msgtag_t _tag;
799   l4_utcb_t *_utcb;
800   char *_current_msg;
801   unsigned _pos;
802   unsigned char _current_buf;
803 };
804
805 template< typename T >
806 inline
807 T read(Istream &s) { T t; s >> t; return t; }
808
809
810 /**
811  * \brief Output stream for IPC marshalling.
812  * \ingroup ipc_fw
813  *
814  * Ipc::Ostream is part of the dynamic IPC marshalling infrastructure, as well
815  * as Ipc::Istream and Ipc::Iostream.
816  *
817  * Ipc::Ostream is an output stream supporting insertion of values into an
818  * IPC message buffer. A IPC message can be marshalled using the
819  * usual insertion operator <<, see \link ipc_stream IPC stream operators
820  * \endlink.
821  *
822  * There exist some special wrapper classes to insert arrays (see
823  * Ipc_buf_cp_out) and indirect strings (see Msg_out_buffer and
824  * Msg_io_buffer). */
825 class Ostream
826 {
827 public:
828   /**
829    * \brief Create an IPC output stream using the given message buffer \a msg.
830    */
831   Ostream(l4_utcb_t *utcb)
832   : _tag(), _utcb(utcb),
833     _current_msg(reinterpret_cast<char *>(l4_utcb_mr_u(_utcb)->mr)),
834     _pos(0), _current_item(0)
835   {}
836
837   /**
838    * \brief Reset the stream to empty, same state as a newly created stream.
839    */
840   void reset()
841   {
842     _pos = 0;
843     _current_item = 0;
844     _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
845   }
846
847   /**
848    * \name Get/Put functions.
849    *
850    * These functions are basically used to implement the insertion operators
851    * (<<) and should not be called directly.
852    *
853    * See \link ipc_stream IPC stream operators \endlink.
854    */
855   //@{
856
857   /**
858    * \brief Put an array with \a size elements of type \a T into the stream.
859    * \param buf A pointer to the array to insert into the buffer.
860    * \param size The number of elements in the array.
861    */
862   template< typename T >
863   void put(T *buf, unsigned long size)
864   {
865     size *= sizeof(T);
866     _pos = cxx::Type_traits<T>::align(_pos);
867     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
868       return;
869
870     __builtin_memcpy(_current_msg + _pos, buf, size);
871     _pos += size;
872   }
873
874   /**
875    * \brief Insert an element of type \a T into the stream.
876    * \param v The element to insert.
877    */
878   template< typename T >
879   void put(T const &v)
880   {
881     _pos = cxx::Type_traits<T>::align(_pos);
882     if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
883       return;
884
885     *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
886     _pos += sizeof(T);
887   }
888
889   int put(Varg const &va)
890   {
891     put(va.tag());
892     put(va.data(), va.length());
893
894     return 0;
895   }
896
897   template< typename T >
898   int put(Varg_t<T> const &va)
899   { return put(static_cast<Varg const &>(va)); }
900
901   /**
902    * \brief Extract the L4 message tag from the stream.
903    * \return the extracted L4 message tag.
904    */
905   l4_msgtag_t tag() const { return _tag; }
906
907   /**
908    * \brief Extract a reference to the L4 message tag from the stream.
909    * \return A reference to the L4 message tag.
910    */
911   l4_msgtag_t &tag() { return _tag; }
912
913   //@}
914
915   /**
916    * \internal
917    * \brief Put a send item into the stream's message buffer.
918    */
919   inline bool put_snd_item(Snd_item const &);
920
921
922   /**
923    * \name IPC operations.
924    */
925   //@{
926
927   /**
928    * \brief Send the message via IPC to the given receiver.
929    * \param dst The destination for the message.
930    */
931   inline l4_msgtag_t send(l4_cap_idx_t dst, long proto = 0, unsigned flags = 0);
932
933   //@}
934
935   /**
936    * \brief Return utcb pointer.
937    */
938   inline l4_utcb_t *utcb() const { return _utcb; }
939 #if 0
940   /**
941    * \brief Get the currently used bytes in the stream.
942    */
943   unsigned long tell() const
944   {
945     register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
946     w -= _current_item * 2;
947     _tag = l4_msgtag(0, w, _current_item, 0);
948   }
949 #endif
950 public:
951   l4_msgtag_t prepare_ipc(long proto = 0, unsigned flags = 0)
952   {
953     register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
954     w -= _current_item * 2;
955     return l4_msgtag(proto, w, _current_item, flags);
956   }
957
958 protected:
959   l4_msgtag_t _tag;
960   l4_utcb_t *_utcb;
961   char *_current_msg;
962   unsigned _pos;
963   unsigned char _current_item;
964 };
965
966
967 /**
968  * \brief Input/Output stream for IPC [un]marshalling.
969  * \ingroup ipc_fw
970  *
971  * The Ipc::Iostream is part of the AW Env IPC framework as well as
972  * Ipc::Istream and Ipc::Ostream.
973  * In particular an Ipc::Iostream is a combination of an Ipc::Istream and an
974  * Ipc::Ostream. It can use either a single message buffer for receiving and
975  * sending messages or a pair of a receive and a send buffer. The stream also
976  * supports combined IPC operations such as call() and reply_and_wait(), which
977  * can be used to implement RPC functionality.
978  */
979 class Iostream : public Istream, public Ostream
980 {
981 public:
982
983   /**
984    * \brief Create an IPC IO stream with a single message buffer.
985    * \param msg The message buffer used as backing store.
986    *
987    * The created IO stream uses the same message buffer for sending and
988    * receiving IPC messages.
989    */
990   explicit Iostream(l4_utcb_t *utcb)
991   : Istream(utcb), Ostream(utcb)
992   {}
993
994
995   /**
996    * \brief Reset the stream to its initial state.
997    *
998    * Input as well as the output stream are reset.
999    */
1000   void reset()
1001   {
1002     Istream::reset();
1003     Ostream::reset();
1004   }
1005
1006
1007   /**
1008    * \name Get/Put functions.
1009    *
1010    * These functions are basically used to implement the insertion operators
1011    * (<<) and should not be called directly.
1012    *
1013    * See \link ipc_stream IPC stream operators \endlink.
1014    */
1015   //@{
1016
1017   using Istream::get;
1018   using Istream::put;
1019   using Ostream::put;
1020
1021   //@}
1022
1023   /**
1024    * \name IPC operations.
1025    */
1026   //@{
1027
1028   /**
1029    * \brief Do an IPC call using the message in the output stream and
1030    *        receiving to the input stream.
1031    * \param dst The destination L4 UID (thread) to call.
1032    * \return the result dope of the IPC operation.
1033    *
1034    * This is a combined IPC operation consisting of a send and a receive
1035    * to/from the given destination \a dst.
1036    *
1037    * A call is usually used by clients for RPCs to a server.
1038    *
1039    */
1040   inline l4_msgtag_t call(l4_cap_idx_t dst);
1041   inline l4_msgtag_t call(l4_cap_idx_t dst, long label);
1042
1043   /**
1044    * \brief Do an IPC reply and wait.
1045    * \param src_dst Input: the destination for the send operation. <br>
1046    *                Output: the source of the received message.
1047    * \return the result dope of the IPC operation.
1048    *
1049    * This is a combined IPC operation consisting of a send operation and
1050    * an open wait for any message.
1051    *
1052    * A reply and wait is usually used by servers that reply to a client
1053    * and wait for the next request by any other client.
1054    */
1055   inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst, long proto = 0)
1056   { return reply_and_wait(src_dst, L4_IPC_SEND_TIMEOUT_0, proto); }
1057
1058   inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1059                                    long proto = 0)
1060   { return send_and_wait(dest, src, L4_IPC_SEND_TIMEOUT_0, proto); }
1061
1062   /**
1063    * \brief Do an IPC reply and wait.
1064    * \param src_dst Input: the destination for the send operation. <br>
1065    *                Output: the source of the received message.
1066    * \param timeout Timeout used for IPC.
1067    * \return the result dope of the IPC operation.
1068    *
1069    * This is a combined IPC operation consisting of a send operation and
1070    * an open wait for any message.
1071    *
1072    * A reply and wait is usually used by servers that reply to a client
1073    * and wait for the next request by any other client.
1074    */
1075   inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst,
1076                                     l4_timeout_t timeout, long proto = 0);
1077   inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1078                                    l4_timeout_t timeout, long proto = 0);
1079   inline l4_msgtag_t reply(l4_timeout_t timeout, long proto = 0);
1080   inline l4_msgtag_t reply(long proto = 0)
1081   { return reply(L4_IPC_SEND_TIMEOUT_0, proto); }
1082
1083   //@}
1084 };
1085
1086
1087 inline bool
1088 Ostream::put_snd_item(Snd_item const &v)
1089 {
1090   typedef Snd_item T;
1091   _pos = cxx::Type_traits<Snd_item>::align(_pos);
1092   if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
1093     return false;
1094
1095   *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
1096   _pos += sizeof(T);
1097   ++_current_item;
1098   return true;
1099 }
1100
1101
1102 inline bool
1103 Istream::put(Buf_item const &item)
1104 {
1105   if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 3)
1106     return false;
1107
1108   l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1109
1110   reinterpret_cast<Buf_item&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1111   _current_buf += 2;
1112   return true;
1113 }
1114
1115
1116 inline bool
1117 Istream::put(Small_buf const &item)
1118 {
1119   if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 2)
1120     return false;
1121
1122   l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1123
1124   reinterpret_cast<Small_buf&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1125   _current_buf += 1;
1126   return true;
1127 }
1128
1129
1130 inline l4_msgtag_t
1131 Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags)
1132 {
1133   l4_msgtag_t tag = prepare_ipc(proto, L4_MSGTAG_FLAGS & flags);
1134   return l4_ipc_send(dst, _utcb, tag, L4_IPC_NEVER);
1135 }
1136
1137 inline l4_msgtag_t
1138 Iostream::call(l4_cap_idx_t dst)
1139 {
1140   l4_msgtag_t tag = prepare_ipc();
1141   tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1142   Istream::tag() = tag;
1143   Istream::_pos = 0;
1144   return tag;
1145 }
1146
1147 inline l4_msgtag_t
1148 Iostream::call(l4_cap_idx_t dst, long label)
1149 {
1150   l4_msgtag_t tag = prepare_ipc(label);
1151   tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1152   Istream::tag() = tag;
1153   Istream::_pos = 0;
1154   return tag;
1155 }
1156
1157
1158 inline l4_msgtag_t
1159 Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto)
1160 {
1161   l4_msgtag_t tag = prepare_ipc(proto);
1162   tag = l4_ipc_reply_and_wait(Ostream::_utcb, tag, src_dst, timeout);
1163   Istream::tag() = tag;
1164   Istream::_pos = 0;
1165   return tag;
1166 }
1167
1168
1169 inline l4_msgtag_t
1170 Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1171                         l4_timeout_t timeout, long proto)
1172 {
1173   l4_msgtag_t tag = prepare_ipc(proto);
1174   tag = l4_ipc_send_and_wait(dest, Ostream::_utcb, tag, src, timeout);
1175   Istream::tag() = tag;
1176   Istream::_pos = 0;
1177   return tag;
1178 }
1179
1180 inline l4_msgtag_t
1181 Iostream::reply(l4_timeout_t timeout, long proto)
1182 {
1183   l4_msgtag_t tag = prepare_ipc(proto);
1184   tag = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, tag, timeout);
1185   Istream::tag() = tag;
1186   Istream::_pos = 0;
1187   return tag;
1188 }
1189
1190 inline l4_msgtag_t
1191 Istream::wait(l4_umword_t *src, l4_timeout_t timeout)
1192 {
1193   l4_msgtag_t res;
1194   res = l4_ipc_wait(_utcb, src, timeout);
1195   tag() = res;
1196   _pos = 0;
1197   return res;
1198 }
1199
1200
1201 inline l4_msgtag_t
1202 Istream::receive(l4_cap_idx_t src, l4_timeout_t timeout)
1203 {
1204   l4_msgtag_t res;
1205   res = l4_ipc_receive(src, _utcb, timeout);
1206   tag() = res;
1207   _pos = 0;
1208   return res;
1209 }
1210
1211 };
1212
1213 } // namespace Ipc
1214
1215 /**
1216  * \brief Extract one element of type \a T from the stream \a s.
1217  * \ingroup ipc_stream
1218  * \param s The stream to extract from.
1219  * \param v Output: extracted value.
1220  * \return the stream \a s.
1221  */
1222 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, bool &v) { s.get(v); return s; }
1223 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, int &v) { s.get(v); return s; }
1224 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long int &v) { s.get(v); return s; }
1225 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long long int &v) { s.get(v); return s; }
1226 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned int &v) { s.get(v); return s; }
1227 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long int &v) { s.get(v); return s; }
1228 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long long int &v) { s.get(v); return s; }
1229 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, short int &v) { s.get(v); return s; }
1230 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned short int &v) { s.get(v); return s; }
1231 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, char &v) { s.get(v); return s; }
1232 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned char &v) { s.get(v); return s; }
1233 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, signed char &v) { s.get(v); return s; }
1234 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Buf_item const &v) { s.put(v); return s; }
1235 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Small_buf const &v) { s.put(v); return s; }
1236 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Snd_item &v)
1237 {
1238   l4_umword_t b, d;
1239   s >> b >> d;
1240   v = L4::Ipc::Snd_item(b,d);
1241   return s;
1242 }
1243 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Varg &v)
1244 { s.get(&v); return s; }
1245
1246
1247 /**
1248  * \brief Extract the L4 message tag from the stream \a s.
1249  * \ingroup ipc_stream
1250  * \param s The stream to extract from.
1251  * \param v Output: the extracted tag.
1252  * \return the stream \a s.
1253  */
1254 inline
1255 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, l4_msgtag_t &v)
1256 {
1257   v = s.tag();
1258   return s;
1259 }
1260
1261 /**
1262  * \brief Extract an array of \a T elements from the stream \a s.
1263  * \ingroup ipc_stream
1264  *
1265  * This operator actually does not copy out the data in the array, but
1266  * returns a pointer into the message buffer itself. This means that the
1267  * data is only valid as long as there is no new data inserted into the stream.
1268  *
1269  * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1270  *
1271  * \param s The stream to extract from.
1272  * \param v Output: pointer to the extracted array (ipc_buf_in()).
1273  * \return the stream \a s.
1274  */
1275 template< typename T >
1276 inline
1277 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1278     L4::Ipc::Buf_in<T> const &v)
1279 {
1280   unsigned long si;
1281   s.get(si);
1282   v.set_size(si);
1283   s.get(L4::Ipc::Msg_ptr<T>(v.buf()), si);
1284   return s;
1285 }
1286
1287 /**
1288  * \brief Extract an element of type \a T from the stream \a s.
1289  * \ingroup ipc_stream
1290  *
1291  * This operator actually does not copy out the data, but
1292  * returns a pointer into the message buffer itself. This means that the
1293  * data is only valid as long as there is no new data inserted into the stream.
1294  *
1295  * See Msg_ptr.
1296  *
1297  * \param s The stream to extract from.
1298  * \param v Output: pointer to the extracted element.
1299  * \return the stream \a s.
1300  */
1301 template< typename T >
1302 inline
1303 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1304     L4::Ipc::Msg_ptr<T> const &v)
1305 {
1306   s.get(v);
1307   return s;
1308 }
1309
1310 /**
1311  * \brief Extract an array of \a T elements from the stream \a s.
1312  * \ingroup ipc_stream
1313  *
1314  * This operator does a copy out of the data into the given buffer.
1315  *
1316  * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1317  *
1318  * \param s The stream to extract from.
1319  * \param v buffer description to copy the array to (ipc_buf_cp_out()).
1320  * \return the stream \a s.
1321  */
1322 template< typename T >
1323 inline
1324 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1325     L4::Ipc::Buf_cp_in<T> const &v)
1326 {
1327   s.get(v.size());
1328   s.get(v.buf(), v.size());
1329   return s;
1330 }
1331
1332
1333 /**
1334  * \brief Insert an element to type \a T into the stream \a s.
1335  * \ingroup ipc_stream
1336  *
1337  * \param s The stream to insert the element \a v.
1338  * \param v The element to insert.
1339  * \return the stream \a s.
1340  */
1341 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, bool v) { s.put(v); return s; }
1342 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, int v) { s.put(v); return s; }
1343 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long int v) { s.put(v); return s; }
1344 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long long int v) { s.put(v); return s; }
1345 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned int v) { s.put(v); return s; }
1346 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long int v) { s.put(v); return s; }
1347 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long long int v) { s.put(v); return s; }
1348 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, short int v) { s.put(v); return s; }
1349 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned short int v) { s.put(v); return s; }
1350 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char v) { s.put(v); return s; }
1351 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned char v) { s.put(v); return s; }
1352 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, signed char v) { s.put(v); return s; }
1353 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Snd_item const &v) { s.put_snd_item(v); return s; }
1354 template< typename T >
1355 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Cap<T> const &v)
1356 { s << L4::Ipc::Snd_fpage(v.fpage()); return s; }
1357
1358 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg const &v)
1359 { s.put(v); return s; }
1360 template< typename T >
1361 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg_t<T> const &v)
1362 { s.put(v); return s; }
1363
1364 /**
1365  * \brief Insert the L4 message tag into the stream \a s.
1366  * \ingroup ipc_stream
1367  *
1368  * \note Only one message tag can be inserted into a stream. Multiple
1369  *       insertions simply overwrite previous insertions.
1370  * \param s The stream to insert the tag \a v.
1371  * \param v The L4 message tag to insert.
1372  * \return the stream \a s.
1373  */
1374 inline
1375 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, l4_msgtag_t const &v)
1376 {
1377   s.tag() = v;
1378   return s;
1379 }
1380
1381 /**
1382  * \brief Insert an array with elements of type \a T into the stream \a s.
1383  * \ingroup ipc_stream
1384  *
1385  * \param s The stream to insert the array \a v.
1386  * \param v The array to insert (see ipc_buf_cp_out()).
1387  * \return the stream \a s.
1388  */
1389 template< typename T >
1390 inline
1391 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s,
1392     L4::Ipc::Buf_cp_out<T> const &v)
1393 {
1394   s.put(v.size());
1395   s.put(v.buf(), v.size());
1396   return s;
1397 }
1398
1399 /**
1400  * \brief Insert a zero terminated character string into the stream \a s.
1401  * \ingroup ipc_stream
1402  *
1403  * \param s The stream to insert the string \a v.
1404  * \param v The string to insert.
1405  * \return the stream \a s.
1406  *
1407  * This operator produces basically the same content as the array insertion,
1408  * however the length of the array is calculated using <c> strlen(\a v) + 1
1409  * </c>. The string is copied into the message including the trailing zero.
1410  */
1411 inline
1412 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char const *v)
1413 {
1414   unsigned long l = __builtin_strlen(v) + 1;
1415   s.put(l);
1416   s.put(v, l);
1417   return s;
1418 }
1419
1420
1421 #ifdef L4_CXX_IPC_BACKWARD_COMPAT
1422 namespace L4 {
1423
1424 template< typename T > class Ipc_buf_cp_out : public Ipc::Buf_cp_out<T> {};
1425 template< typename T > class Ipc_buf_cp_in : public Ipc::Buf_cp_in<T> {};
1426 template< typename T > class Ipc_buf_in : public Ipc::Buf_in<T> {};
1427 template< typename T > class Msg_ptr : public Ipc::Msg_ptr<T> {};
1428
1429 template< typename T >
1430 Ipc::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1431 { return Ipc::Buf_cp_out<T>(v,size); }
1432
1433 template< typename T >
1434 Ipc::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1435 { return Ipc::Buf_cp_in<T>(v,size); }
1436
1437 template< typename T >
1438 Ipc::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1439 { return Ipc::Buf_in<T>(v, size); }
1440
1441 template< typename T >
1442 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1443 { return Ipc::Msg_ptr<T>(p); }
1444
1445 typedef Ipc::Istream Ipc_istream;
1446 typedef Ipc::Ostream Ipc_ostream;
1447 typedef Ipc::Iostream Ipc_iostream;
1448 typedef Ipc::Snd_fpage Snd_fpage;
1449 typedef Ipc::Rcv_fpage Rcv_fpage;
1450 typedef Ipc::Small_buf Small_buf;
1451
1452 }
1453 #endif
1454