Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections;
- using TagTool.Serialization;
- using TagTool.TagGroups;
- using TagTool.Commands;
- namespace TagTool.Common
- {
- /// <summary>
- /// Methods used for setting field differences between two tags, into another tag.
- /// </summary>
- class TagDiff
- {
- /// <summary>
- /// Compares each field in a modified tag (and it's tagblocks) to the equivalent field
- /// in an unmodified tag. Differences result in the equivalent field of the target
- /// tag being set equal to the field in the modified tag.
- /// This includes adding elements and setting fields for contained tagblocks. The target
- /// tag will need to be serialized after calling this method.
- /// </summary>
- /// <param name="structure"> Structure for the target tag. </param>
- /// <param name="structure_a"> Structure for the modified tag. </param>
- /// <param name="structure_b"> Structure for the unmodified tag. </param>
- /// <param name="value"> Value for the target tag. </param>
- /// <param name="value_a"> Value for the modified tag. </param>
- /// <param name="value_b"> Value for the unmodified tag. </param>
- public static void DiffTags(TagStructureInfo structure, TagStructureInfo structure_a, TagStructureInfo structure_b,
- dynamic value, dynamic value_a, dynamic value_b)
- {
- var enumerator = new TagFieldEnumerator(structure); // Creating a TagFieldEnumerator on the target structure
- var enumerator_a = new TagFieldEnumerator(structure_a); // Creating a TagFieldEnumerator on the modified structure
- var enumerator_b = new TagFieldEnumerator(structure_b); // Creating a TagFieldEnumerator on the unmodified structure
- while (enumerator_a.Next()) // Try to move modified-enumerator to next field, and if returns true:
- {
- enumerator.Next(); // Move target-enumerator to next field.
- enumerator_b.Next(); // Move unmodified-enumerator to next field.
- var fieldValue = enumerator.Field.GetValue(value); // Initializing variable to hold target field value
- var fieldValue_a = enumerator_a.Field.GetValue(value_a); // Initializing variable to hold modified field value
- var fieldValue_b = enumerator_b.Field.GetValue(value_b); // Initializing variable to hold unmodified field value
- if (enumerator_a.Field.FieldType.GetInterface(typeof(IList).Name) != null && // Check if the field is a tagblock
- enumerator_a.Field.FieldType.GetInterface(typeof(byte[]).Name) == null // byte[] fields trigger false positives and need to be filtered.
- )
- {
- var tagblockValue = enumerator.Field.GetValue(value) as IList; // Initializing IList variable which represents the target tagblock.
- var elementType = enumerator.Field.FieldType.GenericTypeArguments[0]; // The Type the elements in the tagblock use.
- while (((IList)fieldValue).Count < ((IList)fieldValue_a).Count) // While there are more elements in the modifed tagblock than
- { // in the target tagblock...
- var element = CreateElement(elementType); // Create an element of the given type.
- tagblockValue.Add(element); // Add the element into the tagblock IList variable.
- enumerator.Field.SetValue(value, tagblockValue); // Set the field in the enumerator to the new tagblockValue.
- }
- int i = 0; // Used for keeping count of the current tagblock-element index.
- foreach (var element in (IList)enumerator_a.Field.GetValue(value_a)) // For each element in the modified tagblock field...
- {
- var blockValue = fieldValue[i]; // Represents the element at index "i" in the target tagblock.
- var blockValue_a = fieldValue_a[i]; // Represents the element at index "i" in the modified tagblock.
- var blockStructure = new TagStructureInfo(blockValue.GetType()); // Target tagblock structure.
- var blockStructure_a = new TagStructureInfo(blockValue_a.GetType()); // Modified tagblock structure.
- if (i >= ((IList)fieldValue_b).Count) // If the element is past the base block count all of it's fields
- { // (and tagblocks) must be set equal to the modified version
- // to avoid being left null.
- SetAll(blockStructure, blockStructure_a, blockValue, blockValue_a);
- }
- else
- {
- var blockValue_b = fieldValue_b[i]; // Represents the element at index "i" in the unmodified tagblock.
- var blockStructure_b = new TagStructureInfo(blockValue_b.GetType()); // Unmodified tagblock structure.
- DiffTags(blockStructure, blockStructure_a, blockStructure_b, blockValue, blockValue_a, blockValue_b);
- }
- i++; // Increment the counter.
- }
- }
- // Else if the field isn't a tagblock & the modified field's value is not the same as the unmodified version,
- // set the value in the target version equal to the modified version.
- else if (enumerator_a.Field.GetValue(value_a) != enumerator_b.Field.GetValue(value_b))
- {
- enumerator.Field.SetValue(value, enumerator.Field.GetValue(value_a));
- }
- }
- }
- /// <summary>
- /// Sets all fields in the target tagblock element equal to equivalent fields in the modified element.
- /// This includes adding elements and setting fields for contained tagblocks.
- /// (This can also be used for two tag structures and values, though importing the tag would be
- /// the better option.)
- /// </summary>
- /// <param name="structure"> Structure for the target element. </param>
- /// <param name="structure_a"> Structure for the modified element. </param>
- /// <param name="value"> Value for the target element. </param>
- /// <param name="value_a"> Value for the modified element. </param>
- public static void SetAll(TagStructureInfo structure, TagStructureInfo structure_a, dynamic value, dynamic value_a)
- {
- var enumerator = new TagFieldEnumerator(structure); // Creating a TagFieldEnumerator on the target structure
- var enumerator_a = new TagFieldEnumerator(structure_a); // Creating a TagFieldEnumerator on the modified structure
- while (enumerator_a.Next()) // Try to move modified-enumerator to next field, and if returns true:
- {
- enumerator.Next(); // Move target enumerator to the next field.
- var fieldValue = enumerator.Field.GetValue(value); // Initializing variable to hold target field value
- var fieldValue_a = enumerator_a.Field.GetValue(value_a); // Initializing variable to hold modified field value
- if (enumerator_a.Field.FieldType.GetInterface(typeof(IList).Name) != null && // Check if the field is a tagblock
- enumerator_a.Field.FieldType.GetInterface(typeof(byte[]).Name) == null // byte[] fields trigger false positives and need to be filtered.
- )
- {
- var tagblockValue = enumerator.Field.GetValue(value) as IList; // Initializing IList variable which represents the target tagblock.
- var elementType = enumerator.Field.FieldType.GenericTypeArguments[0]; // The Type the elements in the tagblock use.
- while (((IList)fieldValue).Count < ((IList)fieldValue_a).Count) // While there are more elements in the modifed tagblock than
- { // in the target tagblock...
- var element = CreateElement(elementType); // Create an element of the given type.
- tagblockValue.Add(element); // Add the element into the tagblock IList variable.
- enumerator.Field.SetValue(value, tagblockValue); // Set the field in the enumerator to the new tagblockValue.
- }
- int i = 0; // Used for keeping count of the current tagblock-element index.
- foreach (var element in (IList)enumerator_a.Field.GetValue(value_a)) // For each element in the modified tagblock field...
- {
- var blockValue = fieldValue[i]; // Represents the element at index "i" in the target tagblock.
- var blockValue_a = fieldValue_a[i]; // Represents the element at index "i" in the modified tagblock.
- var blockStructure = new TagStructureInfo(blockValue.GetType()); // Target tagblock structure.
- var blockStructure_a = new TagStructureInfo(blockValue_a.GetType()); // Modified tagblock structure.
- SetAll(blockStructure, blockStructure_a, blockValue, blockValue_a);
- i++; // Increment the counter.
- }
- }
- // Set the value in the target version equal to the modified version.
- enumerator.Field.SetValue(value, enumerator.Field.GetValue(value_a));
- }
- }
- /// <summary>
- /// Creates an empty element to add to a tagblock. Code ripped from AddToCommand.
- /// </summary>
- /// <param name="elementType"> Obtained using "elementType = enumerator.Field.FieldType.GenericTypeArguments[0]",
- /// where enumerator.Field is a tagblock.
- /// </param>
- /// <returns></returns>
- public static object CreateElement(Type elementType)
- {
- var element = Activator.CreateInstance(elementType);
- var isTagStructure = Attribute.IsDefined(elementType, typeof(TagStructureAttribute));
- if (isTagStructure)
- {
- var enumerator = new TagFieldEnumerator(
- new TagStructureInfo(elementType));
- while (enumerator.Next())
- {
- var fieldType = enumerator.Field.FieldType;
- if (fieldType.IsArray && enumerator.Attribute.Count > 0)
- {
- var array = (IList)Activator.CreateInstance(enumerator.Field.FieldType,
- new object[] { enumerator.Attribute.Count });
- for (var i = 0; i < enumerator.Attribute.Count; i++)
- array[i] = CreateElement(fieldType.GetElementType());
- }
- else
- {
- try
- {
- enumerator.Field.SetValue(element, CreateElement(enumerator.Field.FieldType));
- }
- catch
- {
- enumerator.Field.SetValue(element, null);
- }
- }
- }
- }
- return element;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement