crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianUtils/DataBuffer/Primer/DataBufferPrimer.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.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using SymbianUtils.DataBuffer.Entry;

namespace SymbianUtils.DataBuffer.Primer
{
    public class DataBufferPrimer
    {
        #region Delegates & Events
        public delegate void DataBufferPrimerUnhandledLine( DataBufferPrimer aPrimer, DataBuffer aBuffer, string aLine );
        public event DataBufferPrimerUnhandledLine LineNotHandled;

        public delegate void DataBufferPrimerCompleteHandler( DataBufferPrimer aPrimer, DataBuffer aBuffer, uint aFirstByteAddress, uint aLastByteAddress );
        public event DataBufferPrimerCompleteHandler PrimerComplete;
        #endregion

        #region Constructors
        public DataBufferPrimer( DataBuffer aBuffer )
        {
            iDataBuffer = aBuffer;
        }
        #endregion

        #region API
        public void Prime( IEnumerable<string> aLines )
        {
            iDataBuffer.Clear();
            //
            foreach ( string line in aLines )
            {
                PrimeLine( line );
            }

            Primed = true;
        }

        public void PrimeLine( string aLine )
        {
            Match m = iRawDataRegEx.Match( aLine );
            //
            if ( m.Success )
            {
                uint startOfLineAddress = ExtractDataSourceEntryFromMatch( m );
                
                // If the data buffer has never had an address applied to it, then set it now
                if ( iHaveSetFirstAddress == false )
                {
                    iDataBuffer.AddressOffset = startOfLineAddress;
                    iHaveSetFirstAddress = true;
                }
            }
            else if ( LineNotHandled != null )
            {
                LineNotHandled( this, iDataBuffer, aLine );
            }
        }

        public void Prime( string aBinaryFileName )
        {
            Prime( aBinaryFileName, 0 );
        }

        public void Prime( string aBinaryFileName, uint aAddressOfFirstByte )
        {
            FileInfo info = new FileInfo( aBinaryFileName );
            if ( info.Exists )
            {
                int length = (int) info.Length;
                //
                byte[] bytes = new byte[ length ];
                using ( FileStream stream = new FileStream( aBinaryFileName, FileMode.Open, FileAccess.Read, FileShare.Read ) )
                {
                    stream.Read( bytes, 0, length );
                }
                //
                Prime( bytes, aAddressOfFirstByte );
            }
        }

        public void Prime( IEnumerable<byte> aBytes, uint aAddressOfFirstByte )
        {
            iDataBuffer.Clear();

            // Set the starting address
            iDataBuffer.AddressOffset = aAddressOfFirstByte;

            // Read bytes
            uint offset = 0;
            foreach ( byte b in aBytes )
            {
                DataBufferByte entry = new DataBufferByte( b, offset++ );
                iDataBuffer.Add( entry );
            }

            Primed = true;
        }

        public void Prime( DataBuffer aBuffer )
        {
            iDataBuffer.Clear();
            iDataBuffer.Set( aBuffer );
            Primed = true;
        }
        #endregion

        #region Properties
        public bool Primed
        {
            get { return iPrimed; }
            private set
            {
                iPrimed = value;
                if ( Primed )
                {
                    uint firstByte = ( iDataBuffer.Count > 0 ) ? iDataBuffer.First.Address : 0;
                    uint lastByte = ( iDataBuffer.Count > 0 ) ? iDataBuffer.Last.Address : 0;
                    //
                    if ( PrimerComplete != null )
                    {
                        PrimerComplete( this, iDataBuffer, firstByte, lastByte );
                    }
                }
            }
        }
        #endregion

        #region Internal methods
        private uint ExtractDataSourceEntryFromMatch( Match aMatch )
        {
            System.Diagnostics.Debug.Assert( aMatch.Success );

            uint address = 0;
            uint nextExpectedAddress = 0;
            if ( iDataBuffer.Count > 0 )
            {
                nextExpectedAddress = iDataBuffer.Last.Address + 1;
            }
            //
            GroupCollection groups = aMatch.Groups;
            CaptureCollection data = groups[ "Data" ].Captures;

            if ( data.Count > 0 )
            {
                address = System.Convert.ToUInt32( groups[ "Address" ].Value, 16 );

                // Validate the address
                if ( nextExpectedAddress != 0 && address != nextExpectedAddress )
                {
                    throw new Exception( string.Format( "Data is corrupt - expected: 0x{0:x8}, actual: 0x{1:x8}", nextExpectedAddress, address ) );
                }
                else
                {
                    foreach ( Capture capture in data )
                    {
                        string val = capture.Value.Trim();
                        byte b = System.Convert.ToByte( val, 16 );
                        DataBufferByte entry = new DataBufferByte( b, (uint) iDataBuffer.Count );
                        iDataBuffer.Add( entry );
                    }
                }
            }

            return address;
        }
        #endregion

        #region Data members
        private static readonly Regex iRawDataRegEx = new Regex( "(?:.*)\r\n(?<Address>[a-fA-F0-9]{8})\r\n\\:\\s{1}\r\n(?<Data>(?:[a-fA-F0-9]{2})\\s{1}){1,16}\r\n(?:.*)", RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled );
        private readonly DataBuffer iDataBuffer;
        private bool iPrimed = false;
        private bool iHaveSetFirstAddress = false;
        #endregion
    }
}