% StableCharMap - A map of char to any that maintains the insertion order of its elements.

%   Copyright 2012 The MathWorks, Inc.

classdef StableCharMap < handle
    properties ( Access = private )
        BackingData
    end
    
    properties ( SetAccess = private )
        Length
    end

    methods
        function obj = StableCharMap()
            % Backed by a struct array to maintain the insertion order.
            obj.BackingData = struct( 'key', '', 'value', '' );
            obj.Length = 0;
        end

        function val = get( obj, key )
        % get - Get the value for the given key.
            val = obj.BackingData( obj.getKeyIdx( key ) ).value;
        end

        function put( obj, key, value )
        % put - Put or update a key-value pair into the map.
        %
        %   Keys must be non-empty and of type 'char'.
            if ~ischar( key ) || isempty( key )
                error( message( 'parallel:internal:StableCharMapInvalidKey' ) );
            end
            idx = obj.getKeyIdx( key );
            if ~isempty( idx )
                obj.BackingData( idx ).value = value;
            else
                obj.BackingData( obj.Length + 1 ).key = key;
                obj.BackingData( obj.Length + 1 ).value = value;
                obj.Length = obj.Length + 1;
            end
        end

        function val = isKey( obj, key )
        % isKey - Return true if the key exists in the map, false otherwise.
            val = ~isempty( obj.getKeyIdx( key ) );
        end

        function val = keys( obj )
        % keys - Return a cell array of the keys in the map.
            val = { obj.BackingData.key };
        end

        function val = values( obj )
        % values - Return a cell array of the values in the map.
            val = { obj.BackingData.value };
        end

    end

    methods ( Access = private )
        function keyIdx = getKeyIdx( obj, key )
            % Search through the struct array for a key that matches the given key.
            keyIdx = find( strcmp( obj.keys, key ) );
            assert( numel( keyIdx ) <= 1, 'There should not be duplicate keys in the map' );
        end
    end
end
