Advertisement
Guest User

Untitled

a guest
Jul 23rd, 2016
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.66 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using TagTool.Serialization;
  4. using TagTool.TagGroups;
  5. using TagTool.Commands;
  6.  
  7. namespace TagTool.Common
  8. {
  9. /// <summary>
  10. /// Methods used for setting field differences between two tags, into another tag.
  11. /// </summary>
  12. class TagDiff
  13. {
  14. /// <summary>
  15. /// Compares each field in a modified tag (and it's tagblocks) to the equivalent field
  16. /// in an unmodified tag. Differences result in the equivalent field of the target
  17. /// tag being set equal to the field in the modified tag.
  18. /// This includes adding elements and setting fields for contained tagblocks. The target
  19. /// tag will need to be serialized after calling this method.
  20. /// </summary>
  21. /// <param name="structure"> Structure for the target tag. </param>
  22. /// <param name="structure_a"> Structure for the modified tag. </param>
  23. /// <param name="structure_b"> Structure for the unmodified tag. </param>
  24. /// <param name="value"> Value for the target tag. </param>
  25. /// <param name="value_a"> Value for the modified tag. </param>
  26. /// <param name="value_b"> Value for the unmodified tag. </param>
  27. public static void DiffTags(TagStructureInfo structure, TagStructureInfo structure_a, TagStructureInfo structure_b,
  28. dynamic value, dynamic value_a, dynamic value_b)
  29. {
  30. var enumerator = new TagFieldEnumerator(structure); // Creating a TagFieldEnumerator on the target structure
  31. var enumerator_a = new TagFieldEnumerator(structure_a); // Creating a TagFieldEnumerator on the modified structure
  32. var enumerator_b = new TagFieldEnumerator(structure_b); // Creating a TagFieldEnumerator on the unmodified structure
  33.  
  34. while (enumerator_a.Next()) // Try to move modified-enumerator to next field, and if returns true:
  35. {
  36. enumerator.Next(); // Move target-enumerator to next field.
  37. enumerator_b.Next(); // Move unmodified-enumerator to next field.
  38.  
  39. var fieldValue = enumerator.Field.GetValue(value); // Initializing variable to hold target field value
  40. var fieldValue_a = enumerator_a.Field.GetValue(value_a); // Initializing variable to hold modified field value
  41. var fieldValue_b = enumerator_b.Field.GetValue(value_b); // Initializing variable to hold unmodified field value
  42.  
  43. if (enumerator_a.Field.FieldType.GetInterface(typeof(IList).Name) != null && // Check if the field is a tagblock
  44. enumerator_a.Field.FieldType.GetInterface(typeof(byte[]).Name) == null // byte[] fields trigger false positives and need to be filtered.
  45. )
  46. {
  47. var tagblockValue = enumerator.Field.GetValue(value) as IList; // Initializing IList variable which represents the target tagblock.
  48. var elementType = enumerator.Field.FieldType.GenericTypeArguments[0]; // The Type the elements in the tagblock use.
  49.  
  50. while (((IList)fieldValue).Count < ((IList)fieldValue_a).Count) // While there are more elements in the modifed tagblock than
  51. { // in the target tagblock...
  52. var element = CreateElement(elementType); // Create an element of the given type.
  53. tagblockValue.Add(element); // Add the element into the tagblock IList variable.
  54. enumerator.Field.SetValue(value, tagblockValue); // Set the field in the enumerator to the new tagblockValue.
  55. }
  56.  
  57. int i = 0; // Used for keeping count of the current tagblock-element index.
  58. foreach (var element in (IList)enumerator_a.Field.GetValue(value_a)) // For each element in the modified tagblock field...
  59. {
  60. var blockValue = fieldValue[i]; // Represents the element at index "i" in the target tagblock.
  61. var blockValue_a = fieldValue_a[i]; // Represents the element at index "i" in the modified tagblock.
  62.  
  63. var blockStructure = new TagStructureInfo(blockValue.GetType()); // Target tagblock structure.
  64. var blockStructure_a = new TagStructureInfo(blockValue_a.GetType()); // Modified tagblock structure.
  65.  
  66. if (i >= ((IList)fieldValue_b).Count) // If the element is past the base block count all of it's fields
  67. { // (and tagblocks) must be set equal to the modified version
  68. // to avoid being left null.
  69. SetAll(blockStructure, blockStructure_a, blockValue, blockValue_a);
  70. }
  71. else
  72. {
  73. var blockValue_b = fieldValue_b[i]; // Represents the element at index "i" in the unmodified tagblock.
  74. var blockStructure_b = new TagStructureInfo(blockValue_b.GetType()); // Unmodified tagblock structure.
  75.  
  76. DiffTags(blockStructure, blockStructure_a, blockStructure_b, blockValue, blockValue_a, blockValue_b);
  77. }
  78. i++; // Increment the counter.
  79. }
  80. }
  81. // Else if the field isn't a tagblock & the modified field's value is not the same as the unmodified version,
  82. // set the value in the target version equal to the modified version.
  83. else if (enumerator_a.Field.GetValue(value_a) != enumerator_b.Field.GetValue(value_b))
  84. {
  85. enumerator.Field.SetValue(value, enumerator.Field.GetValue(value_a));
  86. }
  87. }
  88. }
  89.  
  90. /// <summary>
  91. /// Sets all fields in the target tagblock element equal to equivalent fields in the modified element.
  92. /// This includes adding elements and setting fields for contained tagblocks.
  93. /// (This can also be used for two tag structures and values, though importing the tag would be
  94. /// the better option.)
  95. /// </summary>
  96. /// <param name="structure"> Structure for the target element. </param>
  97. /// <param name="structure_a"> Structure for the modified element. </param>
  98. /// <param name="value"> Value for the target element. </param>
  99. /// <param name="value_a"> Value for the modified element. </param>
  100. public static void SetAll(TagStructureInfo structure, TagStructureInfo structure_a, dynamic value, dynamic value_a)
  101. {
  102. var enumerator = new TagFieldEnumerator(structure); // Creating a TagFieldEnumerator on the target structure
  103. var enumerator_a = new TagFieldEnumerator(structure_a); // Creating a TagFieldEnumerator on the modified structure
  104.  
  105. while (enumerator_a.Next()) // Try to move modified-enumerator to next field, and if returns true:
  106. {
  107. enumerator.Next(); // Move target enumerator to the next field.
  108.  
  109. var fieldValue = enumerator.Field.GetValue(value); // Initializing variable to hold target field value
  110. var fieldValue_a = enumerator_a.Field.GetValue(value_a); // Initializing variable to hold modified field value
  111.  
  112. if (enumerator_a.Field.FieldType.GetInterface(typeof(IList).Name) != null && // Check if the field is a tagblock
  113. enumerator_a.Field.FieldType.GetInterface(typeof(byte[]).Name) == null // byte[] fields trigger false positives and need to be filtered.
  114. )
  115. {
  116. var tagblockValue = enumerator.Field.GetValue(value) as IList; // Initializing IList variable which represents the target tagblock.
  117. var elementType = enumerator.Field.FieldType.GenericTypeArguments[0]; // The Type the elements in the tagblock use.
  118.  
  119. while (((IList)fieldValue).Count < ((IList)fieldValue_a).Count) // While there are more elements in the modifed tagblock than
  120. { // in the target tagblock...
  121. var element = CreateElement(elementType); // Create an element of the given type.
  122. tagblockValue.Add(element); // Add the element into the tagblock IList variable.
  123. enumerator.Field.SetValue(value, tagblockValue); // Set the field in the enumerator to the new tagblockValue.
  124. }
  125.  
  126. int i = 0; // Used for keeping count of the current tagblock-element index.
  127. foreach (var element in (IList)enumerator_a.Field.GetValue(value_a)) // For each element in the modified tagblock field...
  128. {
  129. var blockValue = fieldValue[i]; // Represents the element at index "i" in the target tagblock.
  130. var blockValue_a = fieldValue_a[i]; // Represents the element at index "i" in the modified tagblock.
  131.  
  132. var blockStructure = new TagStructureInfo(blockValue.GetType()); // Target tagblock structure.
  133. var blockStructure_a = new TagStructureInfo(blockValue_a.GetType()); // Modified tagblock structure.
  134.  
  135. SetAll(blockStructure, blockStructure_a, blockValue, blockValue_a);
  136. i++; // Increment the counter.
  137. }
  138. }
  139. // Set the value in the target version equal to the modified version.
  140. enumerator.Field.SetValue(value, enumerator.Field.GetValue(value_a));
  141. }
  142. }
  143.  
  144. /// <summary>
  145. /// Creates an empty element to add to a tagblock. Code ripped from AddToCommand.
  146. /// </summary>
  147. /// <param name="elementType"> Obtained using "elementType = enumerator.Field.FieldType.GenericTypeArguments[0]",
  148. /// where enumerator.Field is a tagblock.
  149. /// </param>
  150. /// <returns></returns>
  151. public static object CreateElement(Type elementType)
  152. {
  153. var element = Activator.CreateInstance(elementType);
  154.  
  155. var isTagStructure = Attribute.IsDefined(elementType, typeof(TagStructureAttribute));
  156.  
  157. if (isTagStructure)
  158. {
  159. var enumerator = new TagFieldEnumerator(
  160. new TagStructureInfo(elementType));
  161.  
  162. while (enumerator.Next())
  163. {
  164. var fieldType = enumerator.Field.FieldType;
  165.  
  166. if (fieldType.IsArray && enumerator.Attribute.Count > 0)
  167. {
  168. var array = (IList)Activator.CreateInstance(enumerator.Field.FieldType,
  169. new object[] { enumerator.Attribute.Count });
  170.  
  171. for (var i = 0; i < enumerator.Attribute.Count; i++)
  172. array[i] = CreateElement(fieldType.GetElementType());
  173. }
  174. else
  175. {
  176. try
  177. {
  178. enumerator.Field.SetValue(element, CreateElement(enumerator.Field.FieldType));
  179. }
  180. catch
  181. {
  182. enumerator.Field.SetValue(element, null);
  183. }
  184. }
  185. }
  186. }
  187.  
  188. return element;
  189. }
  190. }
  191. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement