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