You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			261 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			261 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------
 | |
| // Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------
 | |
| namespace System.Xml
 | |
| {
 | |
|     using System;
 | |
|     using System.Xml;
 | |
|     using System.Collections;
 | |
|     using System.Diagnostics;
 | |
|     using System.Runtime.Serialization;
 | |
|     using System.Collections.Generic;
 | |
|     using System.Collections.ObjectModel;
 | |
| 
 | |
|     public class XmlBinaryWriterSession
 | |
|     {
 | |
|         PriorityDictionary<string, int> strings;
 | |
|         PriorityDictionary<IXmlDictionary, IntArray> maps;
 | |
|         int nextKey;
 | |
| 
 | |
|         public XmlBinaryWriterSession()
 | |
|         {
 | |
|             this.nextKey = 0;
 | |
|             this.maps = new PriorityDictionary<IXmlDictionary, IntArray>();
 | |
|             this.strings = new PriorityDictionary<string, int>();
 | |
|         }
 | |
| 
 | |
|         public virtual bool TryAdd(XmlDictionaryString value, out int key)
 | |
|         {
 | |
|             IntArray keys;
 | |
|             if (value == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
 | |
| 
 | |
|             if (maps.TryGetValue(value.Dictionary, out keys))
 | |
|             {
 | |
|                 key = (keys[value.Key] - 1);
 | |
| 
 | |
|                 if (key != -1)
 | |
|                 {
 | |
|                     // If the key is already set, then something is wrong
 | |
|                     throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlKeyAlreadyExists)));
 | |
|                 }
 | |
| 
 | |
|                 key = Add(value.Value);
 | |
|                 keys[value.Key] = (key + 1);
 | |
|                 return true;
 | |
|             }
 | |
| 
 | |
|             key = Add(value.Value);
 | |
|             keys = AddKeys(value.Dictionary, value.Key + 1);
 | |
|             keys[value.Key] = (key + 1);
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         int Add(string s)
 | |
|         {
 | |
|             int key = this.nextKey++;
 | |
|             strings.Add(s, key);
 | |
|             return key;
 | |
|         }
 | |
| 
 | |
|         IntArray AddKeys(IXmlDictionary dictionary, int minCount)
 | |
|         {
 | |
|             IntArray keys = new IntArray(Math.Max(minCount, 16));
 | |
|             maps.Add(dictionary, keys);
 | |
|             return keys;
 | |
|         }
 | |
| 
 | |
|         public void Reset()
 | |
|         {
 | |
|             nextKey = 0;
 | |
|             maps.Clear();
 | |
|             strings.Clear();
 | |
|         }
 | |
| 
 | |
|         internal bool TryLookup(XmlDictionaryString s, out int key)
 | |
|         {
 | |
|             IntArray keys;
 | |
|             if (maps.TryGetValue(s.Dictionary, out keys))
 | |
|             {
 | |
|                 key = (keys[s.Key] - 1);
 | |
| 
 | |
|                 if (key != -1)
 | |
|                 {
 | |
|                     return true;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (strings.TryGetValue(s.Value, out key))
 | |
|             {
 | |
|                 if (keys == null)
 | |
|                 {
 | |
|                     keys = AddKeys(s.Dictionary, s.Key + 1);
 | |
|                 }
 | |
| 
 | |
|                 keys[s.Key] = (key + 1);
 | |
|                 return true;
 | |
|             }
 | |
| 
 | |
|             key = -1;
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         class PriorityDictionary<K, V> where K : class
 | |
|         {
 | |
|             Dictionary<K, V> dictionary;
 | |
|             Entry[] list;
 | |
|             int listCount;
 | |
|             int now;
 | |
| 
 | |
|             public PriorityDictionary()
 | |
|             {
 | |
|                 list = new Entry[16];
 | |
|             }
 | |
| 
 | |
|             public void Clear()
 | |
|             {
 | |
|                 now = 0;
 | |
|                 listCount = 0;
 | |
|                 Array.Clear(list, 0, list.Length);
 | |
|                 if (dictionary != null)
 | |
|                     dictionary.Clear();
 | |
|             }
 | |
| 
 | |
|             public bool TryGetValue(K key, out V value)
 | |
|             {
 | |
|                 for (int i = 0; i < listCount; i++)
 | |
|                 {
 | |
|                     if (list[i].Key == key)
 | |
|                     {
 | |
|                         value = list[i].Value;
 | |
|                         list[i].Time = Now;
 | |
|                         return true;
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 for (int i = 0; i < listCount; i++)
 | |
|                 {
 | |
|                     if (list[i].Key.Equals(key))
 | |
|                     {
 | |
|                         value = list[i].Value;
 | |
|                         list[i].Time = Now;
 | |
|                         return true;
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 if (dictionary == null)
 | |
|                 {
 | |
|                     value = default(V);
 | |
|                     return false;
 | |
|                 }
 | |
| 
 | |
|                 if (!dictionary.TryGetValue(key, out value))
 | |
|                 {
 | |
|                     return false;
 | |
|                 }
 | |
| 
 | |
|                 int minIndex = 0;
 | |
|                 int minTime = list[0].Time;
 | |
|                 for (int i = 1; i < listCount; i++)
 | |
|                 {
 | |
|                     if (list[i].Time < minTime)
 | |
|                     {
 | |
|                         minIndex = i;
 | |
|                         minTime = list[i].Time;
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 list[minIndex].Key = key;
 | |
|                 list[minIndex].Value = value;
 | |
|                 list[minIndex].Time = Now;
 | |
|                 return true;
 | |
|             }
 | |
| 
 | |
|             public void Add(K key, V value)
 | |
|             {
 | |
|                 if (listCount < list.Length)
 | |
|                 {
 | |
|                     list[listCount].Key = key;
 | |
|                     list[listCount].Value = value;
 | |
|                     listCount++;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     if (dictionary == null)
 | |
|                     {
 | |
|                         dictionary = new Dictionary<K, V>();
 | |
|                         for (int i = 0; i < listCount; i++)
 | |
|                         {
 | |
|                             dictionary.Add(list[i].Key, list[i].Value);
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     dictionary.Add(key, value);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             int Now
 | |
|             {
 | |
|                 get
 | |
|                 {
 | |
|                     if (++now == int.MaxValue)
 | |
|                     {
 | |
|                         DecreaseAll();
 | |
|                     }
 | |
| 
 | |
|                     return now;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             void DecreaseAll()
 | |
|             {
 | |
|                 for (int i = 0; i < listCount; i++)
 | |
|                 {
 | |
|                     list[i].Time /= 2;
 | |
|                 }
 | |
| 
 | |
|                 now /= 2;
 | |
|             }
 | |
| 
 | |
|             struct Entry
 | |
|             {
 | |
|                 public K Key;
 | |
|                 public V Value;
 | |
|                 public int Time;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         class IntArray
 | |
|         {
 | |
|             int[] array;
 | |
| 
 | |
|             public IntArray(int size)
 | |
|             {
 | |
|                 this.array = new int[size];
 | |
|             }
 | |
| 
 | |
|             public int this[int index]
 | |
|             {
 | |
|                 get
 | |
|                 {
 | |
|                     if (index >= array.Length)
 | |
|                         return 0;
 | |
| 
 | |
|                     return array[index];
 | |
|                 }
 | |
|                 set
 | |
|                 {
 | |
|                     if (index >= array.Length)
 | |
|                     {
 | |
|                         int[] newArray = new int[Math.Max(index + 1, array.Length * 2)];
 | |
|                         Array.Copy(array, newArray, array.Length);
 | |
|                         array = newArray;
 | |
|                     }
 | |
| 
 | |
|                     array[index] = value;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |