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 24namespace L4 { namespace Ipc { 25 26template<typename CHAR = char const, typename LEN = unsigned long> 27struct 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 47template< typename CHAR = char, typename LEN_TYPE = unsigned long, 48 LEN_TYPE MAX = (L4_UTCB_GENERIC_DATA_SIZE * 49 sizeof(l4_umword_t)) / sizeof(CHAR) > 50using String_in_buf = Array_in_buf<CHAR, LEN_TYPE, MAX>; 51#endif 52 53namespace Msg { 54template<typename A, typename LEN> 55struct Clnt_xmit< String<A, LEN> > : Clnt_xmit< Array<A, LEN> > {}; 56 57template<typename A, typename LEN, typename CLASS> 58struct 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 81template<typename A, typename LEN> 82struct 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 103template<typename A, typename LEN> 104struct Clnt_xmit<String<A, LEN> *> : Clnt_xmit<String<A, LEN> &> {}; 105 106template<typename A, typename LEN, typename CLASS> 107struct Svr_val_ops<String<A, LEN>, Dir_out, CLASS> 108: Svr_val_ops<Array_ref<A, LEN>, Dir_out, CLASS> 109{}; 110 111template<typename A, typename LEN> 112struct Is_valid_rpc_type<String<A, LEN> const *> : L4::Types::False {}; 113template<typename A, typename LEN> 114struct Is_valid_rpc_type<String<A, LEN> const &> : L4::Types::False {}; 115 116} // namespace Msg 117 118}} 119