L4Re - L4 Runtime Environment
ipc_string
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  *
9  * As a special exception, you may use this file as part of a free software
10  * library without restriction. Specifically, if other files instantiate
11  * templates or use macros or inline functions from this file, or you compile
12  * this file and link it with other files to produce an executable, this
13  * file does not by itself cause the resulting executable to be covered by
14  * the GNU General Public License. This exception does not however
15  * invalidate any other reasons why the executable file might be covered by
16  * the GNU General Public License.
17  */
18 #pragma once
19 
20 #include "types"
21 #include "ipc_basics"
22 #include "ipc_array"
23 
24 namespace L4 { namespace Ipc {
25 
26 template<typename CHAR = char const, typename LEN = unsigned long>
27 struct String : Array<CHAR, LEN>
28 {
29  static LEN strlength(CHAR *d) { LEN l = 0; while (d[l]) ++l; return l; }
30  String() {}
31  String(CHAR *d) : Array<CHAR, LEN>(strlength(d) + 1, d) {}
32  String(LEN len, CHAR *d) : Array<CHAR, LEN>(len, d) {}
33  void copy_in(CHAR const *s)
34  {
35  if (this->length < 1)
36  return;
37 
38  LEN i;
39  for (i = 0; i < this->length - 1 && s[i]; ++i)
40  this->data[i] = s[i];
41  this->length = i + 1;
42  this->data[i] = CHAR();
43  }
44 };
45 
46 #if __cplusplus >= 201103L
47 template< typename CHAR = char, typename LEN_TYPE = unsigned long,
48  LEN_TYPE MAX = (L4_UTCB_GENERIC_DATA_SIZE *
49  sizeof(l4_umword_t)) / sizeof(CHAR) >
50 using String_in_buf = Array_in_buf<CHAR, LEN_TYPE, MAX>;
51 #endif
52 
53 namespace Msg {
54 template<typename A, typename LEN>
55 struct Clnt_xmit< String<A, LEN> > : Clnt_xmit< Array<A, LEN> > {};
56 
57 template<typename A, typename LEN, typename CLASS>
58 struct Svr_val_ops< String<A, LEN>, Dir_in, CLASS >
59 : Svr_val_ops< Array_ref<A, LEN>, Dir_in, CLASS >
60 {
61  typedef Svr_val_ops< Array_ref<A, LEN>, Dir_in, CLASS > Base;
62  typedef typename Base::svr_type svr_type;
63  using Base::to_svr;
64  static int to_svr(char *msg, unsigned offset, unsigned limit,
65  svr_type &a, Dir_in dir, Cls_data cls)
66  {
67  int r = Base::to_svr(msg, offset, limit, a, dir, cls);
68  if (r < 0)
69  return r;
70 
71  // correct clients send at least the zero terminator
72  if (a.length < 1)
73  return -L4_EMSGTOOSHORT;
74 
75  typedef typename L4::Types::Remove_const<A>::type elem_type;
76  const_cast<elem_type*>(a.data)[a.length - 1] = A();
77  return r;
78  }
79 };
80 
81 template<typename A, typename LEN>
82 struct Clnt_xmit<String<A, LEN> &> : Clnt_xmit<Array<A, LEN> &>
83 {
84  typedef Array<A, LEN> &type;
85 
86  using Clnt_xmit<type>::from_msg;
87  static int from_msg(char *msg, unsigned offset, unsigned limit, long ret,
88  Array<A, LEN> &a, Dir_out dir, Cls_data cls)
89  {
90  int r = Clnt_xmit<type>::from_msg(msg, offset, limit, ret, a, dir, cls);
91  if (r < 0)
92  return r;
93 
94  // check for a bad servers
95  if (a.length < 1)
96  return -L4_EMSGTOOSHORT;
97 
98  a.data[a.length - 1] = A();
99  return r;
100  };
101 };
102 
103 template<typename A, typename LEN>
104 struct Clnt_xmit<String<A, LEN> *> : Clnt_xmit<String<A, LEN> &> {};
105 
106 template<typename A, typename LEN, typename CLASS>
107 struct Svr_val_ops<String<A, LEN>, Dir_out, CLASS>
108 : Svr_val_ops<Array_ref<A, LEN>, Dir_out, CLASS>
109 {};
110 
111 template<typename A, typename LEN>
112 struct Is_valid_rpc_type<String<A, LEN> const *> : L4::Types::False {};
113 template<typename A, typename LEN>
114 struct Is_valid_rpc_type<String<A, LEN> const &> : L4::Types::False {};
115 
116 } // namespace Msg
117 
118 }}