classdef (Hidden) RtIOStreamWrapper < rtw.connectivity.RtIOStream
%RTIOSTREAMWRAPPER rtiostream_wrapper implementation of the RtIOStream 
%                  communications interface for the host. 
%
%   This is an undocumented class. Its methods and properties are likely to
%   change without warning from one release to the next.

%   Copyright 2011-2013 The MathWorks, Inc.
       
    properties (GetAccess = 'private', SetAccess = 'private')
        RtIOStreamLib; % C lib name
        OpenRtIOStreamArgList = {}; % cell array of arg pairs        
    end
    
    methods
        function this = RtIOStreamWrapper(rtIOStreamLib)
            this.RtIOStreamLib = rtIOStreamLib;
        end               
            
        % send via rtiostream_wrapper
        function sizeSent = send(this, data)            
            [retVal, sizeSent] = rtiostream_wrapper(this.getRtIOStreamLib, ...
                                                    'send', ...
                                                    this.getStreamID, ...
                                                    data, ...
                                                    length(data));
            if retVal ~= 0
                msgObj = message('Connectivity:target:ErrorSendReceiveCauses');
                errorCauses = msgObj.getString;                
                error(message('Connectivity:target:ErrorSendingData', errorCauses));
            end
        end
        
        % recv via rtiostream_wrapper 
        function data = recv(this, receiveSize)            
            [retVal, dataArray, recvSize] = rtiostream_wrapper(this.getRtIOStreamLib, ...
                                                          'recv', ...
                                                           this.getStreamID, ...
                                                           receiveSize);                
            if retVal ~= 0
                msgObj = message('Connectivity:target:ErrorSendReceiveCauses');
                errorCauses = msgObj.getString;                                
                error(message('Connectivity:target:ErrorReceivingData', errorCauses));
            end
            data = dataArray(1:recvSize);
        end
        
        function close(this)
            % close via rtiostream_wrapper
            retVal = rtiostream_wrapper(this.RtIOStreamLib, 'close', this.getStreamID);
            if (retVal ~= 0)
                error(message('Connectivity:target:ErrorClosingChannel'));
            end
        end
        
        function setOpenRtIOStreamArgList(this, argList)
        %SETOPENRTIOSTREAMARGLIST sets an argument list for opening the channel
        %
        %   SETOPENRTIOSTREAMARGLIST(THIS,ARGLIST) sets the string ARGLIST as the
        %   argument list to be used when the rtIOStreamOpen function of the
        %   rtiostream shared library is called.
            
            % error out if argList is not a [1,n] or [n,1] cell array of 
            % arg pairs. An empty argList is also allowed.
            if isempty(argList) || (iscell(argList) &&...
                    isvector(argList)  &&...
                    isequal(mod(length(argList),2) , 0))
                this.OpenRtIOStreamArgList = argList;
            else
                error(message('Connectivity:target:BadRtIOStreamArgs', ...
                    'setOpenRtIOStreamArgList'));
            end
            
            
        end

        function setOpenRtIOStreamArgPair(this, argPair)
        %SETOPENRTIOSTREAMARGPAIR sets an argument pair within the argument list
        %
        %   SETOPENRTIOSTREAMARGPAIR(THIS,ARGPAIR) sets the ARGPAIR within the
        %   argument list to be used when the rtIOStreamOpen function of the
        %   rtiostream shared library is called. ARGPAIR must be a cell array
        %   with length equal to two containing a name/value pair; if the name
        %   already exists in the argument list the corresponding value is
        %   replaced.

            assert(iscell(argPair) && isequal(numel(argPair), 2), ...
                ['Input to setOpenRtIOStreamArgPair should be a cell array ',...
                'with length equal to two containing a name/value pair.']);
            
            argName = argPair{1};
            argValue = argPair{2};
            found = 0;
            lenArgList = length(this.OpenRtIOStreamArgList);
            for i=1:lenArgList
                arg=this.OpenRtIOStreamArgList{i};
                if ischar(arg)
                    if strcmp(argName,arg)
                        found = 1;
                        break;
                    end
                end
            end
            if found == 1;
                idx = i; % replace existing value
            else
                idx = lenArgList + 1; % append
            end
            
            this.OpenRtIOStreamArgList{idx} = argName;
            this.OpenRtIOStreamArgList{idx+1} = argValue;
            
        end        
        
        function addOpenRtIOStreamArgs(this, argList)
        %ADDOPENRTIOSTREAMARGS appends to the argument list
        %
        %   ADDOPENRTIOSTREAMARGS(THIS,ARGLIST) appends the cell array of 
        %   strings ARGLIST to the argument list to be used when the 
        %   rtIOStreamOpen function of the rtiostream shared library is 
        %   called.
            
            % error out if argList is not a [1,n] or [n,1] cell array of 
            % arg pairs.
            if ~(iscell(argList) && isvector(argList)  && isequal(mod(length(argList),2), 0))
                error(message('Connectivity:target:BadRtIOStreamArgs', ...
                    'addOpenRtIOStreamArgs'));
            end                
            
            warning(message('Connectivity:target:AddOpenRtIOStreamArgsDeprecated', ...
                                                 mfilename));            
            
            for i=1:length(argList)
                this.OpenRtIOStreamArgList{end+1} = argList{i};
            end
        end
        
        function argList = getOpenRtIOStreamArgList(this)
        %GETOPENRTIOSTREAMARGLIST returns the argument list
        %
        %   ARGLIST = ADDOPENRTIOSTREAMARGLIST(THIS) returns the string ARGLIST
        %   to be used when the rtIOStreamOpen function of the rtiostream shared
        %   library is called.

            argList = this.OpenRtIOStreamArgList;
        end
                
        % return the C lib name
        function rtIOStreamLib = getRtIOStreamLib(this)
            rtIOStreamLib = this.RtIOStreamLib;
        end                
    end
    
    methods (Access = 'protected')
        function streamID = openHook(this, ~)
            % open via rtiostream_wrapper
            streamID = rtiostream_wrapper(this.RtIOStreamLib,'open',...
                this.OpenRtIOStreamArgList{:});
        end
    end
end