crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianUtils/XRef/XRefIdentiferExtractor.cs
changeset 0 818e61de6cd1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianUtils/XRef/XRefIdentiferExtractor.cs	Thu Feb 11 15:50:58 2010 +0200
@@ -0,0 +1,283 @@
+/*
+* 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 SymbianUtils.Strings;
+
+namespace SymbianUtils.XRef
+{
+    public class XRefIdentiferExtractor
+    {
+        #region Constructors
+        public XRefIdentiferExtractor( string aFunction )
+        {
+            iIdentifiers = ExtractSearchableElements( aFunction );
+        }
+        #endregion
+
+        #region Properties
+        public List<XRefIdentifer> Identifiers
+        {
+            get { return iIdentifiers; }
+        }
+        #endregion
+
+        #region Internal methods
+        private static bool ContainsParameters( string aText )
+        {
+            // Search initiall for '(' - if that is found, then
+            // we should also find a closing bracket.
+            bool parameters = false;
+            int openingBracketPos = aText.IndexOf( "(" );
+            //
+            if ( openingBracketPos > 0 )
+            {
+                // Should also be a closing bracket and it should
+                // appear after the opening bracket
+                int closingBracketPos = aText.LastIndexOf( ")" );
+                parameters = ( closingBracketPos > openingBracketPos );
+            }
+            //
+            return parameters;
+        }
+
+        private static string ExtractParameters( ref string aText )
+        {
+            const string KOperatorChevronText = "operator <<";
+
+            // DoAppendFormatList<TDes16, (int)2>(T1&, const T3&, std::__va_list, T2*)
+            // DoAppendFormatList<TDes16, (int)2>(T1&, TBuf<(int)256>, std::__va_list, T2*)
+            // Method<TDes16>::Wibble( something )
+            // Method::Wibble( RPointerArray<HBufC> )
+            // RTest::operator ()(int, int, const unsigned short*)
+            // TDesC16::Left(int) const
+            // CObjectCon::AtL(int) const
+            // User::Panic(const TDesC16&, int)
+            // operator <<(RWriteStream&, const unsigned char&)
+
+            // Handle special case of "operator <<" confusing matters
+            string workingText = aText;
+            int operatorOpeningChevronPos = aText.IndexOf( KOperatorChevronText );
+            if ( operatorOpeningChevronPos >= 0 )
+            {
+                aText = aText.Substring( 0, operatorOpeningChevronPos + KOperatorChevronText.Length );
+                workingText = workingText.Substring( operatorOpeningChevronPos + KOperatorChevronText.Length );
+            }
+            else
+            {
+                aText = string.Empty;
+            }
+
+            string ret = string.Empty;
+            //
+            int closingPos = 0;
+            int openingPos = 0;
+            int templatePos = 0;
+            //
+            while ( openingPos >= 0 )
+            {
+                if ( templatePos >= 0 )
+                    templatePos = workingText.IndexOf( "<", templatePos );
+                openingPos = workingText.IndexOf( "(", openingPos );
+
+                if ( templatePos >= 0 && templatePos < openingPos )
+                {
+                    // Template region appears before the next bracket. Skip
+                    // over all characters until we hit the end of the template
+                    // section
+                    int endingPos = templatePos;
+                    StringParsingUtils.SkipToEndOfSection( ref workingText, ref endingPos, '<', '>' );
+
+                    if ( endingPos < 0 )
+                    {
+                        // Matching closing brace was never found - dealing with operator << ?
+                        templatePos = -1;
+                    }
+                    else
+                    {
+                        // Something like DoAppendFormatList<TDes16, (int)2>(T1&, const T3&, std::__va_list, T2*) ???
+                        templatePos = endingPos;
+                        openingPos = endingPos;
+                    }
+                }
+                else if ( openingPos >= 0 )
+                {
+                    // Skipped over any template nonsense. Work backward from the end 
+                    // in order to locate start of parameters.
+                    closingPos = workingText.LastIndexOf( ')' );
+                    openingPos = closingPos;
+                    StringParsingUtils.SkipToBeginningOfSection( ref workingText, ref openingPos, '(', ')' );
+
+                    string parameters = workingText.Substring( openingPos + 1, ( closingPos - openingPos ) - 1 ).Trim();
+                    ret = parameters;
+                    workingText = workingText.Substring( 0, openingPos + 1 ) + workingText.Substring( closingPos );
+                    aText = aText + workingText;
+                    break;
+                }
+            }
+            //
+            return ret;
+        }
+
+        private static void SplitParameters( string aParams, ref List<string> aEntries )
+        {
+            /*
+             * TPtrC16::TPtrC16(const unsigned short*) 
+             * TPtrC16::TPtrC16(const TDesC16&) 
+             * UserHal::MemoryInfo(TDes8&) 
+             * RHandleBase::Close() 
+             * TBufCBase16::Copy(const TDesC16&, int) 
+             * CBufFlat::NewL(int) 
+             * TBufCBase16::TBufCBase16() 
+             * CServer2::RunL() 
+             * CServer2::StartL(const TDesC16&) 
+             * CServer2::DoCancel() 
+             * CServer2::RunError(int) 
+             * CServer2::DoConnect(const RMessage2&) 
+             * CServer2::CServer2__sub_object(int, CServer2::TServerType) 
+             */
+            string paramType;
+            while ( aParams.Length > 0 )
+            {
+                int commaPos = aParams.IndexOf( "," );
+                //
+                paramType = aParams;
+                if ( commaPos > 0 )
+                {
+                    paramType = aParams.Substring( 0, commaPos ).Trim();
+                    if ( commaPos < aParams.Length )
+                        aParams = aParams.Substring( commaPos + 1 ).Trim();
+                    else
+                        aParams = string.Empty;
+                }
+                else
+                {
+                    // Everything was consumed
+                    aParams = string.Empty;
+                }
+
+                // Add it
+                aEntries.Add( paramType );
+            }
+        }
+
+        private static string[] IdentifyFurtherClassAndMethodInformation( string aEntry )
+        {
+            string[] classAndMethodData = aEntry.Split( new string[] { "::" }, StringSplitOptions.RemoveEmptyEntries );
+            return classAndMethodData;
+        }
+
+        private static List<XRefIdentifer> ExtractSearchableElements( string aFunction )
+        {
+            List<string> workingData = new List<string>();
+
+            // See if this entry contains parameter data?
+            if ( ContainsParameters( aFunction ) )
+            {
+                // This call modifies aFunction so that the parameters are removed
+                string parameters = ExtractParameters( ref aFunction );
+
+                // Now we get the individual parameter elements from the arguments
+                SplitParameters( parameters, ref workingData );
+            }
+
+            // Extract class & method names if present
+            string[] classAndMethodData = aFunction.Split( new string[] { "::" }, StringSplitOptions.RemoveEmptyEntries );
+            if ( classAndMethodData.Length > 0 )
+            {
+                foreach ( string identifiedEntry in classAndMethodData )
+                {
+                    workingData.Add( identifiedEntry );
+                }
+            }
+            else
+            {
+                // Not a class & method - so just take the entire text as a 
+                // global function name
+                workingData.Add( aFunction );
+            }
+
+            // Recursively check for any more class types, e.g. in the following entry:
+            //
+            // CServer2::CServer2__sub_object(int, CServer2::TServerType) 
+            //
+            // We also need to extract CServer2 and TServerType as individual elements
+            for ( int i = workingData.Count - 1; i >= 0; i-- )
+            {
+                string entry = workingData[ i ];
+                string[] furtherSplit = IdentifyFurtherClassAndMethodInformation( entry );
+                if ( furtherSplit != null && furtherSplit.Length > 1 )
+                {
+                    foreach ( string furtherEntry in furtherSplit )
+                    {
+                        workingData.Add( furtherEntry );
+                    }
+
+                    // Remove defunct entry
+                    workingData.RemoveAt( i );
+                }
+            }
+
+            // Clean up phase
+            List<string> cleanedEntries = new List<string>();
+            foreach ( string identifiedEntry in workingData )
+            {
+                string entry = identifiedEntry;
+
+                // Now go through the identified entries and ensure they don't include
+                // any pointer (*), reference (&) or bracketry.
+                int pos = entry.IndexOfAny( new char[] { '*', '+', '&', '[', ']', '<', '>', '(', ')' } );
+                if ( pos >= 0 )
+                {
+                    entry = entry.Substring( 0, pos );
+                }
+
+                // Strip any reserved keywords
+                if ( entry.Length > 0 )
+                {
+                    entry = entry.Replace( "const", string.Empty );
+                    entry = entry.Replace( "static", string.Empty );
+                    entry = entry.Replace( "public", string.Empty );
+                    entry = entry.Replace( "protected", string.Empty );
+                    entry = entry.Replace( "private", string.Empty );
+                    entry = entry.Replace( "__sub_object", string.Empty );
+                    //
+                    if ( !cleanedEntries.Contains( entry ) )
+                    {
+                        cleanedEntries.Add( entry.Trim() );
+                    }
+                }
+            }
+
+            // Convert to XRefIdentifiers
+            List<XRefIdentifer> finalEntries = new List<XRefIdentifer>();
+            foreach ( string cleanedEntry in cleanedEntries )
+            {
+                XRefIdentifer item = new XRefIdentifer( cleanedEntry );
+                finalEntries.Add( item );
+            }
+            //
+            return finalEntries;
+        }
+        #endregion
+
+        #region Data members
+        private readonly List<XRefIdentifer> iIdentifiers;
+        #endregion
+    }
+}