PackableDictionary.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. namespace InABox.Core
  5. {
  6. public abstract class PackableDictionary<T> : Dictionary<string, T>, IPackable
  7. {
  8. public void Pack(BinaryWriter writer)
  9. {
  10. writer.Write(Count);
  11. foreach (var key in Keys)
  12. {
  13. writer.Write(key);
  14. PackItem(writer, this[key]);
  15. }
  16. }
  17. public void Unpack(BinaryReader reader)
  18. {
  19. Clear();
  20. var iCount = reader.ReadInt32();
  21. for (var i = 0; i < iCount; i++)
  22. {
  23. var key = reader.ReadString();
  24. this[key] = UnpackItem(reader);
  25. }
  26. }
  27. public override bool Equals(object obj)
  28. {
  29. var other = obj as PackableDictionary<T>;
  30. if (other == null)
  31. return false;
  32. if (Count != other.Count) // Require equal count.
  33. return false;
  34. foreach (var pair in this)
  35. if (other.TryGetValue(pair.Key, out var value))
  36. {
  37. if (value == null)
  38. {
  39. if (pair.Value != null)
  40. return false;
  41. }
  42. else if (!value.Equals(pair.Value))
  43. {
  44. return false;
  45. }
  46. }
  47. else
  48. {
  49. return false;
  50. }
  51. return true;
  52. }
  53. public abstract void PackItem(BinaryWriter writer, T value);
  54. public abstract T UnpackItem(BinaryReader reader);
  55. }
  56. public class PackableStringDictionary : PackableDictionary<string>
  57. {
  58. public override void PackItem(BinaryWriter writer, string value)
  59. {
  60. writer.Write(value);
  61. }
  62. public override string UnpackItem(BinaryReader reader)
  63. {
  64. return reader.ReadString();
  65. }
  66. }
  67. public class PackableBooleanDictionary : PackableDictionary<bool>
  68. {
  69. public override void PackItem(BinaryWriter writer, bool value)
  70. {
  71. writer.Write(value);
  72. }
  73. public override bool UnpackItem(BinaryReader reader)
  74. {
  75. return reader.ReadBoolean();
  76. }
  77. }
  78. public class PackableObjectDictionary : PackableDictionary<object>
  79. {
  80. private static readonly Dictionary<Type, short> Types = new Dictionary<Type, short>
  81. {
  82. { typeof(object), 0x0000 },
  83. { typeof(string), 0x0001 },
  84. { typeof(string[]), 0x002 },
  85. { typeof(sbyte), 0x1000 },
  86. { typeof(byte), 0x0011 },
  87. { typeof(ushort), 0x0012 },
  88. { typeof(uint), 0x0013 },
  89. { typeof(ulong), 0x0014 },
  90. { typeof(short), 0x0015 },
  91. { typeof(int), 0x0016 },
  92. { typeof(long), 0x0017 },
  93. { typeof(float), 0x0100 },
  94. { typeof(double), 0x0101 },
  95. { typeof(decimal), 0x0102 },
  96. { typeof(TimeSpan), 0x1000 },
  97. { typeof(DateTime), 0x1001 },
  98. { typeof(Guid), 0x1002 }
  99. };
  100. private static readonly Dictionary<short, Type> Indexes = new Dictionary<short, Type>();
  101. static PackableObjectDictionary()
  102. {
  103. foreach (var key in Types.Keys)
  104. Indexes[Types[key]] = key;
  105. }
  106. private static short GetIndex(Type type)
  107. {
  108. if (Types.ContainsKey(type))
  109. return Types[type];
  110. return 0x0000;
  111. }
  112. public static Type GetType(short index)
  113. {
  114. if (Indexes.ContainsKey(index))
  115. return Indexes[index];
  116. return typeof(object);
  117. }
  118. public override void PackItem(BinaryWriter writer, object value)
  119. {
  120. if (value == null)
  121. {
  122. writer.Write(default(short));
  123. writer.Write("");
  124. }
  125. else
  126. {
  127. var type = GetIndex(value.GetType());
  128. writer.Write(type);
  129. writer.Write(CoreUtils.TypedValueToString(value));
  130. }
  131. }
  132. public override object UnpackItem(BinaryReader reader)
  133. {
  134. var index = reader.ReadInt16();
  135. var type = GetType(index);
  136. var value = reader.ReadString();
  137. if (type == typeof(object) && string.IsNullOrEmpty(value))
  138. return null;
  139. return CoreUtils.StringToTypedValue(value, type);
  140. }
  141. }
  142. }