Created
September 19, 2011 04:50
-
-
Save xiangwan/1225981 to your computer and use it in GitHub Desktop.
Revisions
-
向晚 renamed this gist
May 29, 2012 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
向晚 revised this gist
Sep 19, 2011 . 1 changed file with 205 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,205 @@ /// <summary> /// Serializer Class. /// </summary> public class Serializer { //types: // N = null // s = string // i = int // d = double // a = array (hashtable) private Dictionary<Hashtable, bool> seenHashtables; //for serialize (to infinte prevent loops) private Dictionary<ArrayList, bool> seenArrayLists; //for serialize (to infinte prevent loops) lol private int pos; //for unserialize public bool XMLSafe = true; //This member tells the serializer wether or not to strip carriage returns from strings when serializing and adding them back in when deserializing //http://www.w3.org/TR/REC-xml/#sec-line-ends public Encoding StringEncoding = new System.Text.UTF8Encoding(); private System.Globalization.NumberFormatInfo nfi; public Serializer() { this.nfi = new System.Globalization.NumberFormatInfo(); this.nfi.NumberGroupSeparator = ""; this.nfi.NumberDecimalSeparator = "."; } public string Serialize(object obj) { this.seenArrayLists = new Dictionary<ArrayList, bool>(); this.seenHashtables = new Dictionary<Hashtable, bool>(); return this.serialize(obj, new StringBuilder()).ToString(); }//Serialize(object obj) private StringBuilder serialize(object obj, StringBuilder sb) { if (obj == null) { return sb.Append("N;"); } else if (obj is string) { string str = (string)obj; if (this.XMLSafe) { str = str.Replace("\r\n", "\n");//replace \r\n with \n str = str.Replace("\r", "\n");//replace \r not followed by \n with a single \n Should we do this? } return sb.Append("s:" + this.StringEncoding.GetByteCount(str) + ":\"" + str + "\";"); } else if (obj is bool) { return sb.Append("b:" + (((bool)obj) ? "1" : "0") + ";"); } else if (obj is int) { int i = (int)obj; return sb.Append("i:" + i.ToString(this.nfi) + ";"); } else if (obj is double) { double d = (double)obj; return sb.Append("d:" + d.ToString(this.nfi) + ";"); } else if (obj is ArrayList) { if (this.seenArrayLists.ContainsKey((ArrayList)obj)) return sb.Append("N;");//cycle detected else this.seenArrayLists.Add((ArrayList)obj, true); ArrayList a = (ArrayList)obj; sb.Append("a:" + a.Count + ":{"); for (int i = 0; i < a.Count; i++) { this.serialize(i, sb); this.serialize(a[i], sb); } sb.Append("}"); return sb; } else if (obj is Hashtable) { if (this.seenHashtables.ContainsKey((Hashtable)obj)) return sb.Append("N;");//cycle detected else this.seenHashtables.Add((Hashtable)obj, true); Hashtable a = (Hashtable)obj; sb.Append("a:" + a.Count + ":{"); foreach (DictionaryEntry entry in a) { this.serialize(entry.Key, sb); this.serialize(entry.Value, sb); } sb.Append("}"); return sb; } else { return sb; } }//Serialize(object obj) public object Deserialize(string str) { this.pos = 0; return deserialize(str); }//Deserialize(string str) private object deserialize(string str) { if (str == null || str.Length <= this.pos) return new Object(); int start, end, length; string stLen; switch (str[this.pos]) { case 'N': this.pos += 2; return null; case 'b': char chBool; chBool = str[pos + 2]; this.pos += 4; return chBool == '1'; case 'i': string stInt; start = str.IndexOf(":", this.pos) + 1; end = str.IndexOf(";", start); stInt = str.Substring(start, end - start); this.pos += 3 + stInt.Length; return Int32.Parse(stInt, this.nfi); case 'd': string stDouble; start = str.IndexOf(":", this.pos) + 1; end = str.IndexOf(";", start); stDouble = str.Substring(start, end - start); this.pos += 3 + stDouble.Length; return Double.Parse(stDouble, this.nfi); case 's': start = str.IndexOf(":", this.pos) + 1; end = str.IndexOf(":", start); stLen = str.Substring(start, end - start); int bytelen = Int32.Parse(stLen); length = bytelen; //This is the byte length, not the character length - so we migth //need to shorten it before usage. This also implies bounds checking if ((end + 2 + length) >= str.Length) length = str.Length - 2 - end; string stRet = str.Substring(end + 2, length); while (this.StringEncoding.GetByteCount(stRet) > bytelen) { length--; stRet = str.Substring(end + 2, length); } this.pos += 6 + stLen.Length + length; if (this.XMLSafe) { stRet = stRet.Replace("\n", "\r\n"); } return stRet; case 'a': //if keys are ints 0 through N, returns an ArrayList, else returns Hashtable start = str.IndexOf(":", this.pos) + 1; end = str.IndexOf(":", start); stLen = str.Substring(start, end - start); length = Int32.Parse(stLen); Hashtable htRet = new Hashtable(length); ArrayList alRet = new ArrayList(length); this.pos += 4 + stLen.Length; //a:Len:{ for (int i = 0; i < length; i++) { //read key object key = deserialize(str); //read value object val = deserialize(str); if (alRet != null) { if (key is int && (int)key == alRet.Count) alRet.Add(val); else alRet = null; } htRet[key] = val; } this.pos++; //skip the } if (this.pos < str.Length && str[this.pos] == ';')//skipping our old extra array semi-colon bug (er... php's weirdness) this.pos++; if (alRet != null) return alRet; else return htRet; default: return ""; }//switch }//unserialzie(object) }//class Serializer -
向晚 created this gist
Sep 19, 2011 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,206 @@ /// <summary> /// Serializer Class. /// </summary> public class Serializer { //types: // N = null // s = string // i = int // d = double // a = array (hashtable) private Dictionary<Hashtable, bool> seenHashtables; //for serialize (to infinte prevent loops) private Dictionary<ArrayList, bool> seenArrayLists; //for serialize (to infinte prevent loops) lol private int pos; //for unserialize public bool XMLSafe = true; //This member tells the serializer wether or not to strip carriage returns from strings when serializing and adding them back in when deserializing //http://www.w3.org/TR/REC-xml/#sec-line-ends public Encoding StringEncoding = new System.Text.UTF8Encoding(); private System.Globalization.NumberFormatInfo nfi; public Serializer() { this.nfi = new System.Globalization.NumberFormatInfo(); this.nfi.NumberGroupSeparator = ""; this.nfi.NumberDecimalSeparator = "."; } public string Serialize(object obj) { this.seenArrayLists = new Dictionary<ArrayList, bool>(); this.seenHashtables = new Dictionary<Hashtable, bool>(); return this.serialize(obj, new StringBuilder()).ToString(); }//Serialize(object obj) private StringBuilder serialize(object obj, StringBuilder sb) { if (obj == null) { return sb.Append("N;"); } else if (obj is string) { string str = (string)obj; if (this.XMLSafe) { str = str.Replace("\r\n", "\n");//replace \r\n with \n str = str.Replace("\r", "\n");//replace \r not followed by \n with a single \n Should we do this? } return sb.Append("s:" + this.StringEncoding.GetByteCount(str) + ":\"" + str + "\";"); } else if (obj is bool) { return sb.Append("b:" + (((bool)obj) ? "1" : "0") + ";"); } else if (obj is int) { int i = (int)obj; return sb.Append("i:" + i.ToString(this.nfi) + ";"); } else if (obj is double) { double d = (double)obj; return sb.Append("d:" + d.ToString(this.nfi) + ";"); } else if (obj is ArrayList) { if (this.seenArrayLists.ContainsKey((ArrayList)obj)) return sb.Append("N;");//cycle detected else this.seenArrayLists.Add((ArrayList)obj, true); ArrayList a = (ArrayList)obj; sb.Append("a:" + a.Count + ":{"); for (int i = 0; i < a.Count; i++) { this.serialize(i, sb); this.serialize(a[i], sb); } sb.Append("}"); return sb; } else if (obj is Hashtable) { if (this.seenHashtables.ContainsKey((Hashtable)obj)) return sb.Append("N;");//cycle detected else this.seenHashtables.Add((Hashtable)obj, true); Hashtable a = (Hashtable)obj; sb.Append("a:" + a.Count + ":{"); foreach (DictionaryEntry entry in a) { this.serialize(entry.Key, sb); this.serialize(entry.Value, sb); } sb.Append("}"); return sb; } else { return sb; } }//Serialize(object obj) public object Deserialize(string str) { this.pos = 0; return deserialize(str); }//Deserialize(string str) private object deserialize(string str) { if (str == null || str.Length <= this.pos) return new Object(); int start, end, length; string stLen; switch (str[this.pos]) { case 'N': this.pos += 2; return null; case 'b': char chBool; chBool = str[pos + 2]; this.pos += 4; return chBool == '1'; case 'i': string stInt; start = str.IndexOf(":", this.pos) + 1; end = str.IndexOf(";", start); stInt = str.Substring(start, end - start); this.pos += 3 + stInt.Length; return Int32.Parse(stInt, this.nfi); case 'd': string stDouble; start = str.IndexOf(":", this.pos) + 1; end = str.IndexOf(";", start); stDouble = str.Substring(start, end - start); this.pos += 3 + stDouble.Length; return Double.Parse(stDouble, this.nfi); case 's': start = str.IndexOf(":", this.pos) + 1; end = str.IndexOf(":", start); stLen = str.Substring(start, end - start); int bytelen = Int32.Parse(stLen); length = bytelen; //This is the byte length, not the character length - so we migth //need to shorten it before usage. This also implies bounds checking if ((end + 2 + length) >= str.Length) length = str.Length - 2 - end; string stRet = str.Substring(end + 2, length); while (this.StringEncoding.GetByteCount(stRet) > bytelen) { length--; stRet = str.Substring(end + 2, length); } this.pos += 6 + stLen.Length + length; if (this.XMLSafe) { stRet = stRet.Replace("\n", "\r\n"); } return stRet; case 'a': //if keys are ints 0 through N, returns an ArrayList, else returns Hashtable start = str.IndexOf(":", this.pos) + 1; end = str.IndexOf(":", start); stLen = str.Substring(start, end - start); length = Int32.Parse(stLen); Hashtable htRet = new Hashtable(length); ArrayList alRet = new ArrayList(length); this.pos += 4 + stLen.Length; //a:Len:{ for (int i = 0; i < length; i++) { //read key object key = deserialize(str); //read value object val = deserialize(str); if (alRet != null) { if (key is int && (int)key == alRet.Count) alRet.Add(val); else alRet = null; } htRet[key] = val; } this.pos++; //skip the } if (this.pos < str.Length && str[this.pos] == ';')//skipping our old extra array semi-colon bug (er... php's weirdness) this.pos++; if (alRet != null) return alRet; else return htRet; default: return ""; }//switch }//unserialzie(object) }//class Serializer