// vi:set ft=cpp: -*- Mode: C++ -*- /* * (c) 2014 Alexander Warg * * This file is part of TUD:OS and distributed under the terms of the * GNU General Public License 2. * Please see the COPYING-GPL-2 file for details. * * As a special exception, you may use this file as part of a free software * library without restriction. Specifically, if other files instantiate * templates or use macros or inline functions from this file, or you compile * this file and link it with other files to produce an executable, this * file does not by itself cause the resulting executable to be covered by * the GNU General Public License. This exception does not however * invalidate any other reasons why the executable file might be covered by * the GNU General Public License. */ #pragma once #include "types" #include "ipc_basics" namespace L4 { namespace Ipc L4_EXPORT { // --------------------------------------------------------------- /** * Dynamically sized output array of type T. * \tparam T The data-type of each array element. * * Ret_array<> is a special dynamically sized output array * where the number of transmitted elements is passed in * the return value of the call (if positive) */ template struct L4_EXPORT Ret_array { typedef T const **ptr_type; T *value; unsigned max; Ret_array() {} Ret_array(T *v, unsigned max) : value(v), max(max) {} }; namespace Msg { template struct Elem< Ret_array > { enum { Is_optional = false }; typedef Ret_array type; typedef typename type::ptr_type arg_type; typedef type svr_type; typedef type svr_arg_type; }; template struct Is_valid_rpc_type *> : L4::Types::False {}; template struct Is_valid_rpc_type &> : L4::Types::False {}; template struct Is_valid_rpc_type const &> : L4::Types::False {}; template struct Is_valid_rpc_type const *> : L4::Types::False {}; template struct Class< Ret_array > : Class::type {}; template struct Direction< Ret_array > : Dir_out {}; template struct Clnt_val_ops : Clnt_noops { using Clnt_noops::from_msg; static int from_msg(char *msg, unsigned offset, unsigned limit, long ret, A const *&arg, Dir_out, Cls_data) { offset = align_to(offset); arg = reinterpret_cast(msg + offset); if (L4_UNLIKELY(!check_size(offset, limit, ret))) return -1; return offset + ret * sizeof(A); } }; template struct Svr_val_ops, Dir_out, CLASS> : Svr_noops > { typedef Ret_array ret_array; using Svr_noops::from_svr; static int from_svr(char *, unsigned offset, unsigned limit, long ret, ret_array const &, Dir_out, CLASS) { offset = align_to(offset); if (L4_UNLIKELY(!check_size(offset, limit, ret))) return -1; offset += sizeof(A) * ret; return offset; } using Svr_noops::to_svr; static int to_svr(char *msg, unsigned offset, unsigned limit, ret_array &arg, Dir_out, CLASS) { // there can be actually no limit check here, as this // is variably sized output array // FIXME: we could somehow makesure that this is the last // output value... offset = align_to(offset); arg = ret_array(reinterpret_cast(msg + offset), (limit - offset) / sizeof(A)); // FIXME: we dont know the length of the array here so, cheat return offset; } }; } // namespace Msg }}