Advertisement
Guest User

Untitled

a guest
May 26th, 2015
240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.79 KB | None | 0 0
  1. public class PhpArrayConverter
  2. {
  3. //types:
  4. // N = null
  5. // s = string
  6. // i = int
  7. // d = double
  8. // a = array (hashtable)
  9.  
  10. private readonly NumberFormatInfo numberFormatInfo;
  11. public Encoding StringEncoding = new UTF8Encoding();
  12.  
  13. public bool XmlSafe = true;
  14. //This member tells the serializer wether or not to strip carriage returns from strings when serializing and adding them back in when deserializing
  15.  
  16. private int pos; //for unserialize
  17. private Dictionary<ArrayList, bool> seenArrayLists; //for serialize (to infinte prevent loops) lol
  18. private Dictionary<Hashtable, bool> seenHashtables; //for serialize (to infinte prevent loops)
  19.  
  20. public PhpArrayConverter()
  21. {
  22. numberFormatInfo = new NumberFormatInfo();
  23. numberFormatInfo.NumberGroupSeparator = "";
  24. numberFormatInfo.NumberDecimalSeparator = ".";
  25. }
  26.  
  27. public string Serialize(object obj)
  28. {
  29. seenArrayLists = new Dictionary<ArrayList, bool>();
  30. seenHashtables = new Dictionary<Hashtable, bool>();
  31.  
  32. return SerializeInternal(obj, new StringBuilder()).ToString();
  33. }
  34.  
  35. public object Deserialize(string str)
  36. {
  37. pos = 0;
  38. return DeserializeInternal(str);
  39. }
  40.  
  41. private StringBuilder SerializeInternal(object obj, StringBuilder sb)
  42. {
  43. if (obj == null)
  44. {
  45. return sb.Append("N;");
  46. }
  47. if (obj is string)
  48. {
  49. var str = (string) obj;
  50. if (XmlSafe)
  51. {
  52. str = str.Replace("\r\n", "\n"); //replace \r\n with \n
  53. str = str.Replace("\r", "\n"); //replace \r not followed by \n with a single \n Should we do this?
  54. }
  55. return sb.Append("s:" + StringEncoding.GetByteCount(str) + ":\"" + str + "\";");
  56. }
  57. if (obj is bool)
  58. {
  59. return sb.Append("b:" + (((bool) obj) ? "1" : "0") + ";");
  60. }
  61. if (obj is int)
  62. {
  63. var i = (int) obj;
  64. return sb.Append("i:" + i.ToString(numberFormatInfo) + ";");
  65. }
  66. if (obj is double)
  67. {
  68. var d = (double) obj;
  69.  
  70. return sb.Append("d:" + d.ToString(numberFormatInfo) + ";");
  71. }
  72. if (obj is ArrayList)
  73. {
  74. if (seenArrayLists.ContainsKey((ArrayList) obj))
  75. return sb.Append("N;"); //cycle detected
  76.  
  77. seenArrayLists.Add((ArrayList) obj, true);
  78.  
  79. var a = (ArrayList) obj;
  80. sb.Append("a:" + a.Count + ":{");
  81. for (int i = 0; i < a.Count; i++)
  82. {
  83. SerializeInternal(i, sb);
  84. SerializeInternal(a[i], sb);
  85. }
  86. sb.Append("}");
  87. return sb;
  88. }
  89. if (obj is Hashtable)
  90. {
  91. if (seenHashtables.ContainsKey((Hashtable) obj))
  92. return sb.Append("N;"); //cycle detected
  93. seenHashtables.Add((Hashtable) obj, true);
  94.  
  95. var a = (Hashtable) obj;
  96. sb.Append("a:" + a.Count + ":{");
  97. foreach (DictionaryEntry entry in a)
  98. {
  99. SerializeInternal(entry.Key, sb);
  100. SerializeInternal(entry.Value, sb);
  101. }
  102. sb.Append("}");
  103. return sb;
  104. }
  105.  
  106. return sb;
  107. }
  108.  
  109. private object DeserializeInternal(string str)
  110. {
  111. if (str == null || str.Length <= pos)
  112. return new Object();
  113.  
  114. int start, end, length;
  115. string stLen;
  116. switch (str[pos])
  117. {
  118. case 'N':
  119. pos += 2;
  120. return null;
  121. case 'b':
  122. char chBool = str[pos + 2];
  123. pos += 4;
  124. return chBool == '1';
  125. case 'i':
  126. start = str.IndexOf(":", pos, StringComparison.Ordinal) + 1;
  127. end = str.IndexOf(";", start, StringComparison.Ordinal);
  128. string stInt = str.Substring(start, end - start);
  129. pos += 3 + stInt.Length;
  130. return Int32.Parse(stInt, numberFormatInfo);
  131. case 'd':
  132. start = str.IndexOf(":", pos, StringComparison.Ordinal) + 1;
  133. end = str.IndexOf(";", start, StringComparison.Ordinal);
  134. string stDouble = str.Substring(start, end - start);
  135. pos += 3 + stDouble.Length;
  136. return Double.Parse(stDouble, numberFormatInfo);
  137. case 's':
  138. start = str.IndexOf(":", pos, StringComparison.Ordinal) + 1;
  139. end = str.IndexOf(":", start, StringComparison.Ordinal);
  140. stLen = str.Substring(start, end - start);
  141. int bytelen = Int32.Parse(stLen);
  142. length = bytelen;
  143. //This is the byte length, not the character length - so we migth
  144. //need to shorten it before usage. This also implies bounds checking
  145. if ((end + 2 + length) >= str.Length) length = str.Length - 2 - end;
  146. string stRet = str.Substring(end + 2, length);
  147. while (StringEncoding.GetByteCount(stRet) > bytelen)
  148. {
  149. length--;
  150. stRet = str.Substring(end + 2, length);
  151. }
  152. pos += 6 + stLen.Length + length;
  153. if (XmlSafe)
  154. {
  155. stRet = stRet.Replace("\n", "\r\n");
  156. }
  157. return stRet;
  158. case 'a':
  159. //if keys are ints 0 through N, returns an ArrayList, else returns Hashtable
  160. start = str.IndexOf(":", pos, StringComparison.Ordinal) + 1;
  161. end = str.IndexOf(":", start, StringComparison.Ordinal);
  162. stLen = str.Substring(start, end - start);
  163. length = Int32.Parse(stLen);
  164. var htRet = new Hashtable(length);
  165. var alRet = new ArrayList(length);
  166. pos += 4 + stLen.Length; //a:Len:{
  167. for (int i = 0; i < length; i++)
  168. {
  169. //read key
  170. object key = DeserializeInternal(str);
  171. //read value
  172. object val = DeserializeInternal(str);
  173.  
  174. if (alRet != null)
  175. {
  176. if (key is int && (int) key == alRet.Count)
  177. alRet.Add(val);
  178. else
  179. alRet = null;
  180. }
  181. htRet[key] = val;
  182. }
  183. pos++; //skip the }
  184. if (pos < str.Length && str[pos] == ';')
  185. //skipping our old extra array semi-colon bug (er... php's weirdness)
  186. pos++;
  187. if (alRet != null)
  188. return alRet;
  189. return htRet;
  190. default:
  191. return "";
  192. } //switch
  193. }
  194. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement