classdef StackDriver < handle
% This class represents a driver to run a simulation with stack profiling

%   Copyright 2021 The MathWorks, Inc.
    
    properties(Access = 'public')
        PtrDataType; % data type returned by the driver
        HeaderFile; % header file to be included
        SourceFile; % source file to be compiled
        IncludePaths; % include folders
        DriverFunction; % driver function - no arguments
    end

    properties(Access = 'public', Hidden)
        Defines = {}; % list of defines
    end
    
    properties (Constant = true)
        % list of allowed types for the stack pointer
        ValidDataTypes = {'uint8', 'uint16', 'uint32', 'uint64'};
    end
    
    methods
        function obj = StackDriver()
            obj.PtrDataType = coder.profile.StackDriver.ValidDataTypes{end};
        end
        
        function set.PtrDataType(this, ptrDataType)
            % set pointer type
            narginchk(2, 2);
            % strip any trailing "_T/t" (backwards compatibility)
            if any(strcmp(ptrDataType(end-1:end),{'_T', '_t'}))
                ptrDataType = ptrDataType(1:end-2);
            end
            validTypes =  coder.profile.StackDriver.ValidDataTypes;
            
            if ~any(strcmp(ptrDataType, validTypes))
                validTypeStr = validTypes{1};
                for i = 2:length(validTypes)
                    validTypeStr = sprintf('%s, %s', validTypeStr, validTypes{i});
                end
                DAStudio.error('CoderProfile:ExecutionStack:ConnectivityConfigWrongType',...
                               ptrDataType, validTypeStr);
            end

            this.PtrDataType = ptrDataType;
        end
        
        function set.HeaderFile(this, headerFile)
            % set main header file
            narginchk(2, 2);
            this.HeaderFile = headerFile;
        end
        
        function set.SourceFile(this, sourceFile)
            % set main source file
            narginchk(2, 2);
            this.SourceFile = sourceFile;
        end
        
        function set.IncludePaths(this, includePaths)
            % set include paths
            narginchk(2, 2);
            validateattributes(includePaths, ...
                {'cell'}, {'vector'}, ...
                'coder.profile.StackDriver.setIncludeFolders', ...
                'defines', 2);
            this.IncludePaths = includePaths;
        end
        
        function set.DriverFunction(this, driverFunction)
            % set the name of the driver function to call
            narginchk(2, 2);
            this.DriverFunction= driverFunction;
        end
        
        function set.Defines(this, defines)
            % set additional defines
            narginchk(2, 2);
            validateattributes(defines, ...
                {'cell'}, {'vector'}, ...
                'coder.profile.StackDriver.setDefines', ...
                'defines', 2);
            
            this.Defines = defines;
        end
    end

    methods(Access = public, Hidden)
        function lType = getCodeType(this)
            % return the type to use in the instrumentation code
            lType = sprintf('%s_T', this.PtrDataType);
        end
        
        function lPtrSize = getPtrSizeInBits(this)
            lPtrSizeStr = strrep(this.PtrDataType, 'uint', '');
            lPtrSize = str2num(lPtrSizeStr); %#ok<ST2NM>
        end
    end

end

