The Labs \ Source Viewer \ SSCLI \ System.Security.Util \ TokenBasedSet

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. //
  16. // TokenBasedSet.cs
  17. //
  18. namespace System.Security.Util
  19. {
  20.     using System;
  21.     using System.Collections;
  22.     using System.Security.Permissions;
  23.     using System.Runtime.Serialization;
  24.    
  25.     [Serializable()]
  26.     internal class TokenBasedSet
  27.     {
  28.        
  29.        
  30.         // Following 3 fields are used only for serialization compat purposes: DO NOT USE THESE EVER!
  31.         #pragma warning disable 414
  32.         private int m_initSize = 24;
  33.         private int m_increment = 8;
  34.         #pragma warning restore 414
  35.         private object[] m_objSet;
  36.         // END -> Serialization only fields
  37.        
  38.         [OptionalField(VersionAdded = 2)]
  39.         private object m_Obj;
  40.         [OptionalField(VersionAdded = 2)]
  41.         private object[] m_Set;
  42.        
  43.         private int m_cElt;
  44.         private int m_maxIndex;
  45.        
  46.        
  47.         [OnDeserialized()]
  48.         private void OnDeserialized(StreamingContext ctx)
  49.         {
  50.             OnDeserializedInternal();
  51.         }
  52.         private void OnDeserializedInternal()
  53.         {
  54.             //v1.x case
  55.             if (m_objSet != null) {
  56.                 if (m_cElt == 1)
  57.                     m_Obj = m_objSet[m_maxIndex];
  58.                 else
  59.                     m_Set = m_objSet;
  60.                 m_objSet = null;
  61.             }
  62.             // Nothing to do for the v2.0 and beyond case
  63.         }
  64.        
  65.         [OnSerializing()]
  66.         private void OnSerializing(StreamingContext ctx)
  67.         {
  68.            
  69.             if ((ctx.State & ~(StreamingContextStates.Clone | StreamingContextStates.CrossAppDomain)) != 0) {
  70.                 //Nothing special for the v2 and beyond case
  71.                
  72.                 // for the v1.x case, we need to create m_objSet if necessary
  73.                 if (m_cElt == 1) {
  74.                     m_objSet = new object[m_maxIndex + 1];
  75.                     m_objSet[m_maxIndex] = m_Obj;
  76.                 }
  77.                 else if (m_cElt > 0) {
  78.                     // Array case:
  79.                     m_objSet = m_Set;
  80.                 }
  81.                
  82.             }
  83.         }
  84.         [OnSerialized()]
  85.         private void OnSerialized(StreamingContext ctx)
  86.         {
  87.             if ((ctx.State & ~(StreamingContextStates.Clone | StreamingContextStates.CrossAppDomain)) != 0) {
  88.                 m_objSet = null;
  89.                
  90.             }
  91.         }
  92.        
  93.        
  94.         internal bool MoveNext(ref TokenBasedSetEnumerator e)
  95.         {
  96.             switch (m_cElt) {
  97.                 case 0:
  98.                     return false;
  99.                 case 1:
  100.                    
  101.                     if (e.Index == -1) {
  102.                         e.Index = m_maxIndex;
  103.                         e.Current = m_Obj;
  104.                         return true;
  105.                     }
  106.                     else {
  107.                         e.Index = (short)(m_maxIndex + 1);
  108.                         e.Current = null;
  109.                         return false;
  110.                     }
  111.                     break;
  112.                 default:
  113.                    
  114.                     while (++e.Index <= m_maxIndex) {
  115.                         e.Current = m_Set[e.Index];
  116.                        
  117.                         if (e.Current != null)
  118.                             return true;
  119.                     }
  120.                    
  121.                     e.Current = null;
  122.                     return false;
  123.             }
  124.         }
  125.        
  126.         internal TokenBasedSet()
  127.         {
  128.             Reset();
  129.         }
  130.        
  131.         internal TokenBasedSet(TokenBasedSet tbSet)
  132.         {
  133.             if (tbSet == null) {
  134.                 Reset();
  135.                 return;
  136.             }
  137.            
  138.             if (tbSet.m_cElt > 1) {
  139.                 object[] aObj = tbSet.m_Set;
  140.                 int aLen = aObj.Length;
  141.                
  142.                 object[] aNew = new object[aLen];
  143.                 System.Array.Copy(aObj, 0, aNew, 0, aLen);
  144.                
  145.                 m_Set = aNew;
  146.             }
  147.             else {
  148.                 m_Obj = tbSet.m_Obj;
  149.             }
  150.            
  151.             m_cElt = tbSet.m_cElt;
  152.             m_maxIndex = tbSet.m_maxIndex;
  153.         }
  154.        
  155.         internal void Reset()
  156.         {
  157.             m_Obj = null;
  158.             m_Set = null;
  159.             m_cElt = 0;
  160.             m_maxIndex = -1;
  161.         }
  162.        
  163.         internal void SetItem(int index, object item)
  164.         {
  165.             object[] aObj = null;
  166.            
  167.             if (item == null) {
  168.                 RemoveItem(index);
  169.                 return;
  170.             }
  171.            
  172.             switch (m_cElt) {
  173.                 case 0:
  174.                     // on the first item, we don't create an array, we merely remember it's index and value
  175.                     // this this the 99% case
  176.                     m_cElt = 1;
  177.                     m_maxIndex = (short)index;
  178.                     m_Obj = item;
  179.                     break;
  180.                 case 1:
  181.                    
  182.                     // we have to decide if a 2nd item has indeed been added and create the array
  183.                     // if it has
  184.                     if (index == m_maxIndex) {
  185.                         // replacing the one existing item
  186.                         m_Obj = item;
  187.                     }
  188.                     else {
  189.                         // adding a second distinct permission
  190.                         object objSaved = m_Obj;
  191.                         int iMax = Math.Max(m_maxIndex, index);
  192.                        
  193.                         aObj = new object[iMax + 1];
  194.                         aObj[m_maxIndex] = objSaved;
  195.                         aObj[index] = item;
  196.                         m_maxIndex = (short)iMax;
  197.                         m_cElt = 2;
  198.                         m_Set = aObj;
  199.                         m_Obj = null;
  200.                     }
  201.                     break;
  202.                 default:
  203.                    
  204.                     // this is the general case code for when there is really an array
  205.                    
  206.                     aObj = m_Set;
  207.                    
  208.                     // we are now adding an item, check if we need to grow
  209.                    
  210.                     if (index >= aObj.Length) {
  211.                         object[] newset = new object[index + 1];
  212.                         System.Array.Copy(aObj, 0, newset, 0, m_maxIndex + 1);
  213.                         m_maxIndex = (short)index;
  214.                         newset[index] = item;
  215.                         m_Set = newset;
  216.                         m_cElt++;
  217.                     }
  218.                     else {
  219.                         if (aObj[index] == null)
  220.                             m_cElt++;
  221.                        
  222.                         aObj[index] = item;
  223.                        
  224.                         if (index > m_maxIndex)
  225.                             m_maxIndex = (short)index;
  226.                     }
  227.                     break;
  228.             }
  229.         }
  230.        
  231.         internal object GetItem(int index)
  232.         {
  233.             switch (m_cElt) {
  234.                 case 0:
  235.                     return null;
  236.                 case 1:
  237.                    
  238.                     if (index == m_maxIndex)
  239.                         return m_Obj;
  240.                     else
  241.                         return null;
  242.                     break;
  243.                 default:
  244.                     if (index < m_Set.Length)
  245.                         return m_Set[index];
  246.                     else
  247.                         return null;
  248.                     break;
  249.             }
  250.         }
  251.        
  252.         internal object RemoveItem(int index)
  253.         {
  254.             object ret = null;
  255.            
  256.             switch (m_cElt) {
  257.                 case 0:
  258.                     ret = null;
  259.                     break;
  260.                 case 1:
  261.                    
  262.                     if (index != m_maxIndex) {
  263.                         // removing a permission we don't have ignore it
  264.                         ret = null;
  265.                     }
  266.                     else {
  267.                         // removing the permission we have at the moment
  268.                         ret = m_Obj;
  269.                         Reset();
  270.                     }
  271.                     break;
  272.                 default:
  273.                    
  274.                     // this is the general case code for when there is really an array
  275.                    
  276.                     // we are removing an item
  277.                     if (index < m_Set.Length && m_Set[index] != null) {
  278.                         // ok we really deleted something at this point
  279.                        
  280.                         ret = m_Set[index];
  281.                        
  282.                         m_Set[index] = null;
  283.                         m_cElt--;
  284.                        
  285.                         if (index == m_maxIndex)
  286.                             ResetMaxIndex(m_Set);
  287.                        
  288.                         // collapse the array
  289.                         if (m_cElt == 1) {
  290.                             m_Obj = m_Set[m_maxIndex];
  291.                             m_Set = null;
  292.                         }
  293.                     }
  294.                     break;
  295.             }
  296.            
  297.             return ret;
  298.         }
  299.        
  300.         private void ResetMaxIndex(object[] aObj)
  301.         {
  302.             int i;
  303.            
  304.             // Start at the end of the array, and
  305.             // scan backwards for the first non-null
  306.             // slot. That is the new maxIndex.
  307.             for (i = aObj.Length - 1; i >= 0; i--) {
  308.                 if (aObj[i] != null) {
  309.                     m_maxIndex = (short)i;
  310.                     return;
  311.                 }
  312.             }
  313.            
  314.             m_maxIndex = -1;
  315.         }
  316.         internal int GetStartingIndex()
  317.         {
  318.             if (m_cElt <= 1)
  319.                 return m_maxIndex;
  320.             return 0;
  321.         }
  322.         internal int GetCount()
  323.         {
  324.             return m_cElt;
  325.         }
  326.        
  327.         internal int GetMaxUsedIndex()
  328.         {
  329.             return m_maxIndex;
  330.         }
  331.        
  332.         internal bool FastIsEmpty()
  333.         {
  334.             return m_cElt == 0;
  335.         }
  336.        
  337.         // Used to merge two distinct TokenBasedSets (used currently only in PermissionSet Deserialization)
  338.         internal TokenBasedSet SpecialUnion(TokenBasedSet other, ref bool canUnrestrictedOverride)
  339.         {
  340.             // This gets called from PermissionSet.OnDeserialized and it's possible that the TokenBasedSets have
  341.             // not been subjected to VTS callbacks yet
  342.             OnDeserializedInternal();
  343.             TokenBasedSet unionSet = new TokenBasedSet();
  344.             int maxMax;
  345.             if (other != null) {
  346.                 other.OnDeserializedInternal();
  347.                 maxMax = this.GetMaxUsedIndex() > other.GetMaxUsedIndex() ? this.GetMaxUsedIndex() : other.GetMaxUsedIndex();
  348.             }
  349.             else
  350.                 maxMax = this.GetMaxUsedIndex();
  351.            
  352.             for (int i = 0; i <= maxMax; ++i) {
  353.                 object thisObj = this.GetItem(i);
  354.                 IPermission thisPerm = thisObj as IPermission;
  355.                 ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory;
  356.                
  357.                 object otherObj = (other != null) ? other.GetItem(i) : null;
  358.                 IPermission otherPerm = otherObj as IPermission;
  359.                 ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory;
  360.                
  361.                 if (thisObj == null && otherObj == null)
  362.                     continue;
  363.                
  364.                
  365.                 if (thisObj == null) {
  366.                     if (otherElem != null) {
  367.                         otherPerm = PermissionSet.CreatePerm(otherElem, false);
  368.                     }
  369.                    
  370.                    
  371.                    
  372.                    
  373.                     PermissionToken token = PermissionToken.GetToken(otherPerm);
  374.                    
  375.                     if (token == null) {
  376.                         throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
  377.                     }
  378.                    
  379.                     unionSet.SetItem(token.m_index, otherPerm);
  380.                     if (!CodeAccessPermission.CanUnrestrictedOverride(otherPerm))
  381.                         canUnrestrictedOverride = false;
  382.                 }
  383.                 else if (otherObj == null) {
  384.                     if (thisElem != null) {
  385.                         thisPerm = PermissionSet.CreatePerm(thisElem, false);
  386.                     }
  387.                     PermissionToken token = PermissionToken.GetToken(thisPerm);
  388.                     if (token == null) {
  389.                         throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
  390.                     }
  391.                     unionSet.SetItem(token.m_index, thisPerm);
  392.                     if (!CodeAccessPermission.CanUnrestrictedOverride(thisPerm))
  393.                         canUnrestrictedOverride = false;
  394.                    
  395.                 }
  396.                 else {
  397.                     BCLDebug.Assert((thisObj == null || otherObj == null), "Permission cannot be in both TokenBasedSets");
  398.                 }
  399.             }
  400.             return unionSet;
  401.         }
  402.         internal void SpecialSplit(ref TokenBasedSet unrestrictedPermSet, ref TokenBasedSet normalPermSet, bool ignoreTypeLoadFailures)
  403.         {
  404.             int maxIndex = GetMaxUsedIndex();
  405.            
  406.             for (int i = GetStartingIndex(); i <= maxIndex; ++i) {
  407.                 object obj = GetItem(i);
  408.                 if (obj != null) {
  409.                     IPermission perm = obj as IPermission;
  410.                     if (perm == null)
  411.                         perm = PermissionSet.CreatePerm(obj, ignoreTypeLoadFailures);
  412.                     PermissionToken token = PermissionToken.GetToken(perm);
  413.                    
  414.                     if (perm == null || token == null)
  415.                         continue;
  416.                    
  417.                     if (perm is IUnrestrictedPermission) {
  418.                         // Add to unrestrictedPermSet
  419.                         if (unrestrictedPermSet == null)
  420.                             unrestrictedPermSet = new TokenBasedSet();
  421.                         unrestrictedPermSet.SetItem(token.m_index, perm);
  422.                     }
  423.                     else {
  424.                         // Add to normalPermSet
  425.                         if (normalPermSet == null)
  426.                             normalPermSet = new TokenBasedSet();
  427.                         normalPermSet.SetItem(token.m_index, perm);
  428.                     }
  429.                    
  430.                 }
  431.                
  432.             }
  433.            
  434.         }
  435.     }
  436. }

Developer Fusion