From 49f1209035aac1fcfad5dbbe25f7b2306d3be86c Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 7 Dec 2017 14:19:05 -0800 Subject: Support MSI backends creating custom tables and remove WixToolset.Data.WindowsInstaller --- src/WixToolset.Core.Burn/RowIndexedList.cs | 302 +++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 src/WixToolset.Core.Burn/RowIndexedList.cs (limited to 'src/WixToolset.Core.Burn/RowIndexedList.cs') diff --git a/src/WixToolset.Core.Burn/RowIndexedList.cs b/src/WixToolset.Core.Burn/RowIndexedList.cs new file mode 100644 index 00000000..3a4dad38 --- /dev/null +++ b/src/WixToolset.Core.Burn/RowIndexedList.cs @@ -0,0 +1,302 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Core.Burn +{ + using System; + using System.Collections.Generic; + using WixToolset.Data.WindowsInstaller; + + /// + /// A list of rows indexed by their primary key. Unlike a + /// this indexed list will track rows in their added order and will allow rows with + /// duplicate keys to be added to the list, although only the first row will be indexed. + /// + public sealed class RowIndexedList : IList where T : Row + { + private Dictionary index; + private List rows; + private List duplicates; + + /// + /// Creates an empty . + /// + public RowIndexedList() + { + this.index = new Dictionary(StringComparer.InvariantCulture); + this.rows = new List(); + this.duplicates = new List(); + } + + /// + /// Creates and populates a with the rows from the given enumerator. + /// + /// Rows to index. + public RowIndexedList(IEnumerable rows) + : this() + { + foreach (T row in rows) + { + this.Add(row); + } + } + + /// + /// Creates and populates a with the rows from the given . + /// + /// The table to index. + /// + /// Rows added to the index are not automatically added to the given . + /// + public RowIndexedList(Table table) + : this() + { + if (null != table) + { + foreach (T row in table.Rows) + { + this.Add(row); + } + } + } + + /// + /// Gets the duplicates in the list. + /// + public IEnumerable Duplicates { get { return this.duplicates; } } + + /// + /// Gets the row by integer key. + /// + /// Integer key to look up. + /// Row or null if key is not found. + public T Get(int key) + { + return this.Get(key.ToString()); + } + + /// + /// Gets the row by string key. + /// + /// String key to look up. + /// Row or null if key is not found. + public T Get(string key) + { + T result; + return this.TryGet(key, out result) ? result : null; + } + + /// + /// Gets the row by string key if it exists. + /// + /// Key of row to get. + /// Row found. + /// True if key was found otherwise false. + public bool TryGet(string key, out T row) + { + return this.index.TryGetValue(key, out row); + } + + /// + /// Tries to add a row as long as it would not create a duplicate. + /// + /// Row to add. + /// True if the row as added otherwise false. + public bool TryAdd(T row) + { + try + { + this.index.Add(row.GetKey(), row); + } + catch (ArgumentException) // if the key already exists, bail. + { + return false; + } + + this.rows.Add(row); + return true; + } + + /// + /// Adds a row to the list. If a row with the same key is already index, the row is + /// is not in the index but will still be part of the list and added to the duplicates + /// list. + /// + /// + public void Add(T row) + { + this.rows.Add(row); + try + { + this.index.Add(row.GetKey(), row); + } + catch (ArgumentException) // if the key already exists, we have a duplicate. + { + this.duplicates.Add(row); + } + } + + /// + /// Gets the index of a row. + /// + /// Iterates through the list of rows to find the index of a particular row. + /// Index of row or -1 if not found. + public int IndexOf(T row) + { + return this.rows.IndexOf(row); + } + + /// + /// Inserts a row at a particular index of the list. + /// + /// Index to insert the row after. + /// Row to insert. + public void Insert(int index, T row) + { + this.rows.Insert(index, row); + try + { + this.index.Add(row.GetKey(), row); + } + catch (ArgumentException) // if the key already exists, we have a duplicate. + { + this.duplicates.Add(row); + } + } + + /// + /// Removes a row from a particular index. + /// + /// Index to remove the row at. + public void RemoveAt(int index) + { + T row = this.rows[index]; + + this.rows.RemoveAt(index); + + T indexRow; + if (this.index.TryGetValue(row.GetKey(), out indexRow) && indexRow == row) + { + this.index.Remove(row.GetKey()); + } + else // only try to remove from duplicates if the row was not indexed (if it was indexed, it wasn't a dupe). + { + this.duplicates.Remove(row); + } + } + + /// + /// Gets or sets a row at the specified index. + /// + /// Index to get the row. + /// Row at specified index. + public T this[int index] + { + get + { + return this.rows[index]; + } + set + { + this.rows[index] = value; + try + { + this.index.Add(value.GetKey(), value); + } + catch (ArgumentException) // if the key already exists, we have a duplicate. + { + this.duplicates.Add(value); + } + } + } + + /// + /// Empties the list and it's index. + /// + public void Clear() + { + this.index.Clear(); + this.rows.Clear(); + this.duplicates.Clear(); + } + + /// + /// Searches the list for a row without using the index. + /// + /// Row to look for in the list. + /// True if the row is in the list, otherwise false. + public bool Contains(T row) + { + return this.rows.Contains(row); + } + + /// + /// Copies the rows of the list to an array. + /// + /// Array to copy the list into. + /// Index to start copying at. + public void CopyTo(T[] array, int arrayIndex) + { + this.rows.CopyTo(array, arrayIndex); + } + + /// + /// Number of rows in the list. + /// + public int Count + { + get { return this.rows.Count; } + } + + /// + /// Indicates whether the list is read-only. Always false. + /// + public bool IsReadOnly + { + get { return false; } + } + + /// + /// Removes a row from the list. Indexed rows will be removed but the colleciton will NOT + /// promote duplicates to the index automatically. The duplicate would also need to be removed + /// and re-added to be indexed. + /// + /// + /// + public bool Remove(T row) + { + bool removed = this.rows.Remove(row); + if (removed) + { + T indexRow; + if (this.index.TryGetValue(row.GetKey(), out indexRow) && indexRow == row) + { + this.index.Remove(row.GetKey()); + } + else // only try to remove from duplicates if the row was not indexed (if it was indexed, it wasn't a dupe). + { + this.duplicates.Remove(row); + } + } + + return removed; + } + + /// + /// Gets an enumerator over the whole list. + /// + /// List enumerator. + public IEnumerator GetEnumerator() + { + return this.rows.GetEnumerator(); + } + + /// + /// Gets an untyped enumerator over the whole list. + /// + /// Untyped list enumerator. + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.rows.GetEnumerator(); + } + } +} -- cgit v1.2.3-55-g6feb