crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianUtils/Range/AddressRange.cs
author Matti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:50:58 +0200
changeset 0 818e61de6cd1
permissions -rw-r--r--
Add initial version of Crash Analyser cmdline under EPL

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
* 
* Description:
*
*/
using System;
using System.Text;
using System.Text.RegularExpressions;

namespace SymbianUtils.Range
{
	public class AddressRange : IComparable<AddressRange>
    {
        #region Delegates & events
        public delegate void ChangeHandler( AddressRange aAddressRange );
        public event ChangeHandler RangeChanged; 
        #endregion

        #region Constructors
        public AddressRange()
		{
		}

        public AddressRange( string aSpecifier )
        {
            this.Parse( aSpecifier );
        }

        public AddressRange( uint aMin, uint aMax )
        {
            iMin = aMin;
            iMax = aMax;
        }

        public AddressRange( long aMin, long aMax )
            : this( (uint) aMin, (uint) aMax )
        {
        }

        public AddressRange( AddressRange aCopy )
            : this( aCopy.Min, aCopy.Max )
        {
        }
        #endregion

        #region API
        public void Set( uint aMin, uint aMax )
        {
            iMax = aMax;
            iMin = aMin;
        }

        public bool Contains( uint aAddress )
        {
            bool ret = ( aAddress >= iMin && aAddress <= iMax );
            return ret;
        }

        public bool Contains( long aAddress )
        {
            bool ret = Contains( (uint) aAddress );
            return ret;
        }

        public bool Contains( AddressRange aRange )
        {
            bool ret = Contains( aRange.Min ) && Contains( aRange.Max );
            return ret;
        }

        public void Reset()
        {
            iMin = uint.MaxValue;
            iMax = uint.MinValue;
            //
            OnChanging();
        }

        public void Update( AddressRange aRange )
        {
            AddressRange transaction = TransactionBegin();
            //
            UpdateMin( aRange.Min );
            UpdateMax( aRange.Max );
            //
            TransactionEnd( transaction );
        }

        public void UpdateMin( uint aProposedMin )
        {
            uint old = iMin;
            iMin = Math.Min( iMin, aProposedMin );
            //
            if ( old != iMin )
            {
                OnChanging();
            }
        }

        public void UpdateMax( uint aProposedMax )
        {
            uint old = iMax;
            iMax = Math.Max( iMax, aProposedMax );
            //
            if ( old != iMax )
            {
                OnChanging();
            }
        }

        public void UpdateMin( long aProposedMin )
        {
            UpdateMin( (uint) aProposedMin );
        }

        public void UpdateMax( long aProposedMax )
        {
            UpdateMax( (uint) aProposedMax );
        }

        public void Parse( string aValue )
        {
            Match m = KRegEx.Match( aValue );
            if ( m.Success )
            {
                string min = m.Groups[ "Min" ].Value.Replace( "0x", string.Empty );
                string max = m.Groups[ "Max" ].Value.Replace( "0x", string.Empty );

                // Also need to know if they are hex or decimal specifiers
                int baseMin = ( m.Groups[ 0 ].Value == "0x" ? 16 : 10 );
                int baseMax = ( m.Groups[ 1 ].Value == "0x" ? 16 : 10 );

                // Now convert
                uint valueMin = System.Convert.ToUInt32( min, baseMin );
                uint valueMax = System.Convert.ToUInt32( max, baseMax );

                // Make range...
                AddressRange transaction = TransactionBegin();
                //
                UpdateMin( valueMin );
                UpdateMin( valueMax );
                //
                TransactionEnd( transaction );
            }
            else
            {
                throw new ArgumentException( "Invalid range format - expected [0x]AAA - [0x]BBB" );
            }
        }
        #endregion

        #region Properties
        public uint Min
        {
            get { return iMin; }
            set 
            {
                if ( iMin != value )
                {
                    iMin = value;
                    OnChanging();
                }
            }
        }

        public uint Max
        {
            get { return iMax; }
            set
            {
                if ( iMax != value )
                {
                    iMax = value;
                    OnChanging();
                }
            }
        }

        public uint Size
        {
            get 
            { 
                uint ret = Max - Min + 1;
                return ret;
            }
        }

        public bool IsValid
        {
            get
            {
                bool goodMin = ( iMin != uint.MaxValue );
                bool goodMax = ( iMax != uint.MinValue );
                //
                return ( goodMin && goodMax );
            }
        }
        #endregion

        #region From System.Object
        public override string ToString()
        {
            StringBuilder ret = new StringBuilder();
            ret.AppendFormat( "{0:x8}-{1:x8}", Min, Max );
            return ret.ToString();
        }

        public override int GetHashCode()
        {
            return (int) ( Min ^ Max );
        }

        public override bool Equals( object aObject )
        {
            bool ret = false;
            //
            if ( aObject != null )
            {
                if ( aObject is AddressRange )
                {
                    AddressRange other = (AddressRange) aObject;
                    //
                    int compareMin = other.Min.CompareTo( this.Min );
                    int compareMax = other.Max.CompareTo( this.Max );
                    //
                    ret = ( compareMin == 0 && compareMax == 0 );
                }
                else
                {
                    ret = base.Equals( aObject );
                }
            }
            //
            return ret;
        }
        #endregion

        #region Operators
        public static implicit operator AddressRange( string aSpecifier )
        {
            AddressRange ret = new AddressRange( aSpecifier );
            return ret;
        }
        #endregion

        #region Internal regular expressions
        private static readonly Regex KRegEx = new Regex(
              "(?<Min>(?((0x))0x[A-Fa-f0-9]{1,8}|[0-9]{1,8}))\\s*\\-\\s*(?<"+
              "Max>(?((0x))0x[A-Fa-f0-9]{1,8}|[0-9]{1,8}))",
            RegexOptions.CultureInvariant
            | RegexOptions.Compiled
            );
        #endregion

        #region From IComparable<AddressRange5>
        public int CompareTo( AddressRange aOther )
        {
            int ret = 1;
            //
            if ( aOther != null )
            {
                ret = this.Min.CompareTo( aOther.Min );
            }
            //
            return ret;
        }
        #endregion

        #region Internal methods
        private void OnChanging()
        {
            if ( !InTransaction )
            {
                OnChanged();
            }
        }

        protected virtual void OnChanged()
        {
            if ( RangeChanged != null )
            {
                RangeChanged( this );
            }
        }

        private bool InTransaction
        {
            get { return iTransactionCount > 0; }
        }

        private AddressRange TransactionBegin()
        {
            ++iTransactionCount;
            //
            AddressRange ret = new AddressRange( this.Min, this.Min );
            return ret;
        }

        private void TransactionEnd( AddressRange aTransaction )
        {
            System.Diagnostics.Debug.Assert( iTransactionCount > 0 );
            --iTransactionCount;
            //
            if ( aTransaction.CompareTo( this ) != 0 )
            {
                OnChanging();
            }
        }
        #endregion

        #region Data members
        private uint iMin = uint.MaxValue;
        private uint iMax = uint.MinValue;
        private int iTransactionCount = 0;
        #endregion
    }
}