sysperfana/heapanalyser/Libraries/Engine/MemAnalysisLib/MemAnalysisRegionalCollection.cs
changeset 8 15296fd0af4a
equal deleted inserted replaced
7:8e12a575a9b5 8:15296fd0af4a
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * Redistribution and use in source and binary forms, with or without
       
     6 * modification, are permitted provided that the following conditions are met:
       
     7 *
       
     8 * - Redistributions of source code must retain the above copyright notice,
       
     9 *   this list of conditions and the following disclaimer.
       
    10 * - Redistributions in binary form must reproduce the above copyright notice,
       
    11 *   this list of conditions and the following disclaimer in the documentation
       
    12 *   and/or other materials provided with the distribution.
       
    13 * - Neither the name of Nokia Corporation nor the names of its contributors
       
    14 *   may be used to endorse or promote products derived from this software
       
    15 *   without specific prior written permission.
       
    16 *
       
    17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
       
    18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
       
    21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
       
    22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       
    23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       
    24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
       
    25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       
    26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
       
    27 * POSSIBILITY OF SUCH DAMAGE.
       
    28 * 
       
    29 * Initial Contributors:
       
    30 * Nokia Corporation - initial contribution.
       
    31 *
       
    32 * Contributors:
       
    33 *
       
    34 * Description: 
       
    35 *
       
    36 */
       
    37 
       
    38 using System;
       
    39 using System.Collections;
       
    40 using System.Collections.Generic;
       
    41 using MemAnalysisLib.MemoryOperations.Class;
       
    42 using MemAnalysisLib.MemoryOperations.Functions;
       
    43 using MemAnalysisLib.MemoryOperations.Operations;
       
    44 
       
    45 namespace MemAnalysisLib
       
    46 {
       
    47 	public class MemObjRegionMarker
       
    48 	{
       
    49 		#region Properties
       
    50 		public bool Initialised
       
    51 		{
       
    52 			get
       
    53 			{
       
    54 				return !( LineNumber == KUninitialisedLineNumber && RegionText == KUninitialisedRegionText );
       
    55 			}
       
    56 		}
       
    57 		
       
    58 		public bool MatchedRegionText
       
    59 		{
       
    60 			get { return iMatchedRegionText; }
       
    61 			set { iMatchedRegionText = value; }
       
    62 		}
       
    63 
       
    64 		public string RegionText
       
    65 		{
       
    66 			get { return iRegionText; }
       
    67 			set { iRegionText = value; }
       
    68 		}
       
    69 
       
    70 		public long LineNumber
       
    71 		{
       
    72 			get { return iLineNumber; }
       
    73 			set { iLineNumber = value; }
       
    74 		}
       
    75 		#endregion
       
    76 
       
    77 		#region Internal constants
       
    78 		const long KUninitialisedLineNumber = -1;
       
    79 		const string KUninitialisedRegionText = "__!__!__!UNINIT!__!__!__";
       
    80 		#endregion
       
    81 
       
    82 		#region Data members
       
    83 		private bool iMatchedRegionText;
       
    84 		private string iRegionText = KUninitialisedRegionText;
       
    85 		private long iLineNumber = KUninitialisedLineNumber;
       
    86 		#endregion
       
    87 	}
       
    88 
       
    89 	public class MemObjRegionalCollection
       
    90 	{
       
    91 		#region Constructor & destructor
       
    92 		public MemObjRegionalCollection()
       
    93 		{
       
    94 		}
       
    95 		#endregion
       
    96 
       
    97 		#region API
       
    98 		public void Add( MemOpBase aItem )
       
    99 		{
       
   100 			iItems.Add( aItem );
       
   101 		}
       
   102 
       
   103 		public MemOpBase ItemByAddress( long aCellAddress )
       
   104 		{
       
   105 			int index;
       
   106 			return ItemByAddress( aCellAddress, out index );
       
   107 		}
       
   108 
       
   109 		public MemOpBase ItemByAddress( long aCellAddress, out int aIndex )
       
   110 		{
       
   111 			aIndex = -1;
       
   112 			MemOpBase ret = null;
       
   113 			int count = iItems.Count;
       
   114 			//
       
   115 			for( int i = count-1; i>=0; i-- )
       
   116 			{
       
   117 				MemOpBase item = (MemOpBase) iItems[ i ];
       
   118 				if	( item.CellAddress == aCellAddress )
       
   119 				{
       
   120 					aIndex = i;
       
   121 					ret = item;
       
   122 					break;
       
   123 				}
       
   124 			}
       
   125 			//
       
   126 			return ret;
       
   127 		}
       
   128 
       
   129 		public MemOpBase ItemByAddress( long aCellAddress, TClass aClass )
       
   130 		{
       
   131 			int index;
       
   132 			return ItemByAddress( aCellAddress, aClass, out index );
       
   133 		}
       
   134 
       
   135 		public MemOpBase ItemByAddress( long aCellAddress, TClass aClass, out int aIndex )
       
   136 		{
       
   137 			aIndex = -1;
       
   138 			MemOpBase ret = null;
       
   139 			int count = iItems.Count;
       
   140 			//
       
   141 			for( int i = count-1; i>=0; i-- )
       
   142 			{
       
   143 				MemOpBase item = (MemOpBase) iItems[ i ];
       
   144 				if	( item.CellAddress == aCellAddress )
       
   145 				{
       
   146 					if	( aClass == TClass.ENotApplicable || item.Class == aClass )
       
   147 					{
       
   148 						aIndex = i;
       
   149 						ret = item;
       
   150 						break;
       
   151 					}
       
   152 				}
       
   153 			}
       
   154 			//
       
   155 			return ret;
       
   156 		}
       
   157 
       
   158 		public MemOpBase ItemByOperationIndex( long aOpIndex, TClass aClass, out int aIndex )
       
   159 		{
       
   160 			aIndex = -1;
       
   161 			MemOpBase ret = null;
       
   162 			int count = iItems.Count;
       
   163 			//
       
   164 			for( int i = count-1; i>=0; i-- )
       
   165 			{
       
   166 				MemOpBase item = (MemOpBase) iItems[ i ];
       
   167 				if	( item.OperationIndex == aOpIndex )
       
   168 				{
       
   169 					if	( aClass == TClass.ENotApplicable || item.Class == aClass )
       
   170 					{
       
   171 						aIndex = i;
       
   172 						ret = item;
       
   173 						break;
       
   174 					}
       
   175 				}
       
   176 			}
       
   177 			//
       
   178 			return ret;
       
   179 		}
       
   180 
       
   181 		public bool RemoveByCellAddress( MemOpBase aItem )
       
   182 		{
       
   183 			int index;
       
   184 			bool ret = false;
       
   185 			//
       
   186 			if	( ItemByAddress( aItem.CellAddress, aItem.Class, out index ) != null )
       
   187 			{
       
   188 				iItems.RemoveAt( index );
       
   189 				ret = true;
       
   190 			}
       
   191 			//
       
   192 			return ret;
       
   193 		}
       
   194 		#endregion
       
   195 
       
   196 		#region Properties
       
   197 		public int Count
       
   198 		{
       
   199 			get { return iItems.Count; }
       
   200 		}
       
   201 
       
   202 		public MemOpBase this[int aIndex]
       
   203 		{
       
   204 			get
       
   205 			{
       
   206 				MemOpBase item = (MemOpBase) iItems[aIndex];
       
   207 				return item;
       
   208 			}
       
   209 		}
       
   210 
       
   211 		public MemObjRegionMarker RegionStart
       
   212 		{
       
   213 			get { return iRegionStart; }
       
   214 			set { iRegionStart = value; }
       
   215 		}
       
   216 
       
   217 		public MemObjRegionMarker RegionEnd
       
   218 		{
       
   219 			get { return iRegionEnd; }
       
   220 			set { iRegionEnd = value; }
       
   221 		}
       
   222 
       
   223 		public long AllocationCount
       
   224 		{
       
   225 			get
       
   226 			{
       
   227 				long ret = 0;
       
   228 				//
       
   229 				int count = Count;
       
   230 				for(int i=0; i<count; i++)
       
   231 				{
       
   232 					MemOpBase item = this[i];
       
   233 					if	( item is MemOpAllocation )
       
   234 					{
       
   235 						ret++;
       
   236 					}
       
   237 				}
       
   238 				//
       
   239 				return ret;
       
   240 			}
       
   241 		}
       
   242 
       
   243 		public long DeallocationCount
       
   244 		{
       
   245 			get
       
   246 			{
       
   247 				long ret = 0;
       
   248 				//
       
   249 				int count = Count;
       
   250 				for(int i=0; i<count; i++)
       
   251 				{
       
   252 					MemOpBase item = this[i];
       
   253 					if	( item is MemOpFree )
       
   254 					{
       
   255 						ret++;
       
   256 					}
       
   257 				}
       
   258 				//
       
   259 				return ret;
       
   260 			}
       
   261 		}
       
   262 
       
   263         public long TotalAmountOfAllocatedMemory
       
   264 		{
       
   265 			get
       
   266 			{
       
   267                 long ret = 0;
       
   268                 //
       
   269                 foreach ( MemOpBase op in iItems )
       
   270                 {
       
   271                     if ( op.Class == TClass.EReallocation )
       
   272                     {
       
   273                         #warning Fix me - TotalAmountOfAllocatedMemory is broken for reallocs
       
   274                     }
       
   275                     else if ( op.Class == TClass.EAllocation )
       
   276                     {
       
   277                         MemOpAllocation allocItem = (MemOpAllocation) op;
       
   278                         ret += allocItem.CellSize;
       
   279                     }
       
   280                 }
       
   281                 //
       
   282                 return ret;
       
   283             }
       
   284 		}
       
   285 
       
   286         public long TotalAmountOfDeallocatedMemory
       
   287 		{
       
   288 			get
       
   289 			{
       
   290                 long ret = 0;
       
   291                 //
       
   292                 foreach ( MemOpBase op in iItems )
       
   293                 {
       
   294                     if ( op.Class == TClass.EDeallocation && op.Link != null )
       
   295                     {
       
   296                         MemOpAllocation allocItem = (MemOpAllocation) op.Link;
       
   297                         ret += allocItem.CellSize;
       
   298                     }
       
   299                 }
       
   300                 //
       
   301                 return ret;
       
   302             }
       
   303 		}
       
   304 
       
   305         public long TotalMemoryAllocatedButNotFreed
       
   306 		{
       
   307 			get
       
   308 			{
       
   309                 long ret = 0;
       
   310                 //
       
   311                 foreach ( MemOpBase op in iItems )
       
   312                 {
       
   313                     // Allocated cells without links back to the deleted cells
       
   314                     // must be orphans.
       
   315                     if ( op.Link == null )
       
   316                     {
       
   317                         if ( op.Class == TClass.EAllocation )
       
   318                         {
       
   319                             MemOpAllocation allocItem = (MemOpAllocation) op;
       
   320                             ret += allocItem.CellSize;
       
   321                         }
       
   322                         else if ( op.Class == TClass.EReallocation )
       
   323                         {
       
   324                             #warning Fix me - TotalMemoryAllocatedButNotFreed is broken for reallocs
       
   325                             MemOpReallocation allocItem = (MemOpReallocation) op;
       
   326                             ret += allocItem.CellSize;
       
   327                         }
       
   328                     }
       
   329                 }
       
   330                 //
       
   331                 return ret;
       
   332             }
       
   333 		}
       
   334 		#endregion
       
   335 
       
   336 		#region Internal methods
       
   337 		#endregion
       
   338 
       
   339 		#region Data members
       
   340 		private MemObjRegionMarker iRegionStart = new MemObjRegionMarker();
       
   341 		private MemObjRegionMarker iRegionEnd = new MemObjRegionMarker();
       
   342 		private ArrayList iItems = new ArrayList(50);
       
   343 		#endregion
       
   344 	}
       
   345 
       
   346 	public class MemObjRegionalData
       
   347 	{
       
   348 		#region Constants
       
   349 		const string KOperationOutsideOfRegionText = "Memory operation(s) took place outside of region markers";
       
   350 		#endregion
       
   351 
       
   352 		#region Constructor & destructor
       
   353 		public MemObjRegionalData()
       
   354 		{
       
   355 		}
       
   356 		#endregion
       
   357 
       
   358 		#region API
       
   359 		public void MarkerStartIdentified( string aText, long aLineNumber )
       
   360 		{
       
   361 			if	( iCurrentCollection != null )
       
   362 			{
       
   363 				// We've just finished a collection. Normally this is handled
       
   364 				// by the end item, but if the end item wasn't found, then
       
   365 				// we must do it manually.
       
   366 				CurrentCollectionComplete( KOperationOutsideOfRegionText, aLineNumber - 1, false );
       
   367 			}
       
   368 
       
   369 			// Set the starting items
       
   370 			iCurrentCollection = new MemObjRegionalCollection();
       
   371 			iCurrentCollection.RegionStart.RegionText = aText;
       
   372 			iCurrentCollection.RegionStart.LineNumber = aLineNumber;
       
   373 			iCurrentCollection.RegionStart.MatchedRegionText = true;
       
   374 		}
       
   375 
       
   376 		public void MarkerEndIdentified( string aText, long aLineNumber )
       
   377 		{
       
   378 			CurrentCollectionComplete( aText, aLineNumber, true );
       
   379 		}
       
   380 
       
   381 		public void AllItemsLocated( long aLastLineNumber )
       
   382 		{
       
   383 			// Don't need these anymore
       
   384 			if	( iCurrentCollection != null )
       
   385 			{
       
   386 				iCurrentCollection.RegionEnd.RegionText = "";
       
   387 				iCurrentCollection.RegionEnd.LineNumber = aLastLineNumber;
       
   388 				iCollections.Add( iCurrentCollection );
       
   389 			}
       
   390 			iCurrentCollection = null;
       
   391 			iAllItems.Clear();
       
   392 		}
       
   393 
       
   394 		public void Add( MemOpBase aItem, bool aDiscardAllocAndFreedMatchingCells )
       
   395 		{
       
   396 			#region When deallocating, search for original alloc and link items...
       
   397 			// If the item is a de-allocation, hunt backwards through the allocation
       
   398 			// list until we find the allocating cell. Then setup their two-way relationship
       
   399 			bool throwAwayObject = false;
       
   400 
       
   401 			if	( aItem.IsAllocationType == false )
       
   402 			{
       
   403 				int count = iAllItems.Count;
       
   404 				for(int i=count - 1; i>=0; i--)
       
   405 				{
       
   406 					MemOpBase item = (MemOpBase) iAllItems[i];
       
   407 					//
       
   408 					if	( item.Link == null && item.CellAddress == aItem.CellAddress && item.IsAllocationType != aItem.IsAllocationType )
       
   409 					{
       
   410 						// The item should be the allocation that this de-alloc is associated
       
   411 						// with..
       
   412 						//System.Diagnostics.Debug.Assert( item.IsAllocationType == true ); - User::Realloc screwing things up?
       
   413 						if	( aDiscardAllocAndFreedMatchingCells )
       
   414 						{
       
   415 							// Can ignore both cells. First remove teh previous allocation cell.
       
   416 							iAllItems.RemoveAt( i );
       
   417 
       
   418 							// We don't even add aItem to the 'all items' container.
       
   419 							// However, we still need to remove the linked allocation from it's container.
       
   420 							if	( item.Collection != null )
       
   421 							{
       
   422 								MemObjRegionalCollection collectionForAllocation = (MemObjRegionalCollection) item.Collection;
       
   423 								int colCount = collectionForAllocation.Count;
       
   424 								collectionForAllocation.RemoveByCellAddress( item );
       
   425 
       
   426 								// Make sure we really removed it.
       
   427 								System.Diagnostics.Debug.Assert( collectionForAllocation.Count == colCount - 1 );
       
   428 
       
   429 								// We don't want to log this 'free' operation since it perfectly 
       
   430 								// matched an allocation.
       
   431 								throwAwayObject = true;
       
   432 							}
       
   433 						}
       
   434 						else
       
   435 						{
       
   436 							item.Link = aItem;
       
   437 							aItem.Link = item;
       
   438 						}
       
   439 
       
   440 						break;
       
   441 					}
       
   442 				}
       
   443 			}
       
   444 			#endregion
       
   445 	
       
   446 			// Add the item to our master list...
       
   447 			if	( !throwAwayObject )
       
   448 			{
       
   449 				AddToCollection( aItem );
       
   450 			}
       
   451 		}
       
   452 
       
   453 		public void Add( MemOpReallocation aItem )
       
   454 		{
       
   455 #warning THIS CODE IS TOTALLY BROKEN - RETEST AFTER COLLECING NEW TRACES
       
   456 
       
   457 			/*
       
   458              * The main issue is that it doesn't store the full reallocation chain for repeated reallocations
       
   459              * 
       
   460 			// Locate the original allocation item...
       
   461 			int itemIndex;
       
   462 			int collectionIndex;
       
   463 			MemOpBase item;
       
   464 			MemObjRegionalCollection collection = CollectionByCellAddress( aItem.OriginalCellAddress, TClass.EAllocation, out item, out collectionIndex, out itemIndex );
       
   465 			//
       
   466 			if	( collection != null && item != null )
       
   467 			{
       
   468 				// It should be an allocation item
       
   469 				System.Diagnostics.Debug.Assert( item is MemOpAllocation );
       
   470 
       
   471 				// Update it
       
   472 				MemOpAllocation allocItem = (MemOpAllocation) item;
       
   473 				allocItem.AllocationSize = aItem.AllocationSize;
       
   474 				allocItem.HeapSize = aItem.HeapSize;
       
   475 				allocItem.CellAddress = aItem.CellAddress;
       
   476 
       
   477 				// Associate
       
   478 				aItem.Link = item;
       
   479 
       
   480 				AddToCollection( aItem );
       
   481 			}
       
   482              */
       
   483 		}
       
   484 
       
   485 		public MemObjRegionalCollection CollectionByOperationIndex( long aOpIndex, TClass aClass, out MemOpBase aItem, out int aCollectionIndex, out int aItemIndex )
       
   486 		{
       
   487 			aItem = null;
       
   488 			aCollectionIndex = -1;
       
   489 			aItemIndex = -1;
       
   490 			MemObjRegionalCollection ret = null;
       
   491 
       
   492 			// First check whether the item is in the current collection (if we have one)
       
   493 			if	( iCurrentCollection != null )
       
   494 			{
       
   495 				aItem = iCurrentCollection.ItemByOperationIndex( aOpIndex, aClass, out aItemIndex );
       
   496 				if	( aItem != null )
       
   497 				{
       
   498 					// Yes, it resides in the current collection...
       
   499 					ret = iCurrentCollection;
       
   500 				}
       
   501 			}
       
   502 			else
       
   503 			{
       
   504 				// Need to search the remaining collections. Must search backwards!
       
   505 				int count = iCollections.Count;
       
   506 				for( int i = count-1; i>=0; i-- )
       
   507 				{
       
   508 					MemObjRegionalCollection collection = (MemObjRegionalCollection) iCollections[ i ];
       
   509 					aItem = collection.ItemByOperationIndex( aOpIndex, aClass, out aItemIndex );
       
   510 					if	( aItem != null )
       
   511 					{
       
   512 						// Yes, its in this collection 
       
   513 						ret = collection;
       
   514 						aCollectionIndex = i;
       
   515 						break;
       
   516 					}
       
   517 				}
       
   518 			}
       
   519 
       
   520 			return ret;
       
   521 		}
       
   522 
       
   523         public MemObjRegionalCollection CollectionByCellAddress( long aCellAddress, TClass aClass )
       
   524 		{
       
   525 			int index;
       
   526 			return CollectionByCellAddress( aCellAddress, aClass, out index );
       
   527 		}
       
   528 
       
   529 		public MemObjRegionalCollection CollectionByCellAddress( long aCellAddress, TClass aClass, out int aCollectionIndex )
       
   530 		{
       
   531 			aCollectionIndex = -1;
       
   532 			int itemIndex = -1;
       
   533 			MemOpBase item = null;
       
   534 			return CollectionByCellAddress( aCellAddress, aClass, out item, out aCollectionIndex, out itemIndex );
       
   535 		}
       
   536 		
       
   537 		public MemObjRegionalCollection CollectionByCellAddress( long aCellAddress, TClass aClass, out MemOpBase aItem, out int aCollectionIndex, out int aItemIndex )
       
   538 		{
       
   539 			aItem = null;
       
   540 			aCollectionIndex = -1;
       
   541 			aItemIndex = -1;
       
   542 			MemObjRegionalCollection ret = null;
       
   543 
       
   544 			// First check whether the item is in the current collection (if we have one)
       
   545 			if	( iCurrentCollection != null )
       
   546 			{
       
   547 				aItem = iCurrentCollection.ItemByAddress( aCellAddress, aClass, out aItemIndex );
       
   548 				if	( aItem != null )
       
   549 				{
       
   550 					// Yes, it resides in the current collection...
       
   551 					ret = iCurrentCollection;
       
   552 				}
       
   553 			}
       
   554 			else
       
   555 			{
       
   556 				// Need to search the remaining collections. Must search backwards!
       
   557 				int count = iCollections.Count;
       
   558 				for( int i = count-1; i>=0; i-- )
       
   559 				{
       
   560 					MemObjRegionalCollection collection = (MemObjRegionalCollection) iCollections[ i ];
       
   561 					aItem = collection.ItemByAddress( aCellAddress, aClass, out aItemIndex );
       
   562 					if	( aItem != null )
       
   563 					{
       
   564 						// Yes, its in this collection 
       
   565 						ret = collection;
       
   566 						aCollectionIndex = i;
       
   567 						break;
       
   568 					}
       
   569 				}
       
   570 			}
       
   571 
       
   572 			return ret;
       
   573 		}
       
   574 		#endregion
       
   575 
       
   576 		#region Properties
       
   577 		public int Count
       
   578 		{
       
   579 			get { return iCollections.Count; }
       
   580 		}
       
   581 
       
   582 		public MemObjRegionalCollection this[ int aIndex ]
       
   583 		{
       
   584 			get
       
   585 			{
       
   586 				MemObjRegionalCollection ret = (MemObjRegionalCollection) iCollections[ aIndex ];
       
   587 				return ret;
       
   588 			}
       
   589 		}
       
   590 		#endregion
       
   591 
       
   592 		#region Internal methods
       
   593 		private void AddToCollection( MemOpBase aItem )
       
   594 		{
       
   595 			// Add the item to our master list...
       
   596 			iAllItems.Add( aItem );
       
   597 			aItem.OperationIndex = iAllItems.Count;
       
   598 
       
   599 			// If the start region marker hasn't been initialised, it means
       
   600 			// that the object operation took place outside of an allocation
       
   601 			if	( iCurrentCollection == null || iCurrentCollection.RegionStart.Initialised == false )
       
   602 			{
       
   603 				if	( iCurrentCollection == null )
       
   604 					iCurrentCollection = new MemObjRegionalCollection();
       
   605 
       
   606 				// In this case, we set the start line number to the line upon
       
   607 				// which the operation took place.
       
   608 				iCurrentCollection.RegionStart.LineNumber = aItem.LineNumber;
       
   609 				iCurrentCollection.RegionStart.RegionText = KOperationOutsideOfRegionText;
       
   610 			}
       
   611 
       
   612 			// Associate the item with this collection
       
   613 			aItem.Collection = iCurrentCollection;
       
   614 			iCurrentCollection.Add( aItem );
       
   615 		}
       
   616 		
       
   617 		private void CurrentCollectionComplete( string aText, long aLineNumber, bool aMatchedRegionText )
       
   618 		{
       
   619 			if	( iCurrentCollection != null )
       
   620 			{
       
   621 				iCurrentCollection.RegionEnd.RegionText = aText;
       
   622 				iCurrentCollection.RegionEnd.LineNumber = aLineNumber;
       
   623 				iCurrentCollection.RegionEnd.MatchedRegionText = aMatchedRegionText;
       
   624 				//
       
   625 				iCollections.Add( iCurrentCollection );
       
   626 				iCurrentCollection = null;
       
   627 			}
       
   628 		}
       
   629 		#endregion
       
   630 
       
   631 		#region Data members
       
   632 		private MemObjRegionalCollection iCurrentCollection;
       
   633 		private ArrayList iAllItems = new ArrayList( 5000 );
       
   634 		private ArrayList iCollections = new ArrayList( 100 );
       
   635 		#endregion
       
   636 	}
       
   637 }