PHP Сериализатор

Лучший способ помочь другим, поделиться своими находками.

PHP Сериализатор

Сообщение Sergion 16 июл 2010, 13:37

PHP сериализатор/десериализатор для Unity. Понимает массивы, стринги и прочие радости. Работает по аналогии с PHPшным serialize/unserialize и полностью совместим с ним. Для сериализации используется функция Serialize и для десериализации Unserialize соответственно.
Удобно например для обмена массивами данных с сервером, без всяких XML/JSon (юзаем PHPSerializer.Serialize(array) - и вуаля).

Код: Выделить всё
using UnityEngine;
using System;
using System.Text;
using System.Collections;

public class PHPSerializer : MonoBehaviour {

      //types:
      // s = string
      // i = int
      // d = double
      // a = array (hashtable)

      private ArrayList hashes; //for serialize (to infinte prevent loops)
      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 string Serialize(object obj)
      {
         hashes = new ArrayList();
         return serialize(obj).ToString();
      }//Serialize(object obj)

      private StringBuilder serialize(object obj)
      {
         StringBuilder sb = new StringBuilder();
         if(obj == null)
         {
            return sb.Append("N;");
         }
         else if(obj is string)
         {
            string str = (string)obj;
            if(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:" + str.Length + ":\"" + 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 + ";");
         }         
         else if(obj is double)
         {
            double d = (double)obj;
            return sb.Append("d:" + d + ";");
         }
         else if(obj is ArrayList)
         {
            if(hashes.Contains(obj.GetHashCode()))
               return sb.Append("N;");
            else
               hashes.Add(obj.GetHashCode());

            ArrayList a = (ArrayList)obj;
            sb.Append("a:" + a.Count + ":{");
            for(int i = 0; i < a.Count; i++)
            {
               sb.Append(serialize(i));
               sb.Append(serialize(a[i]));
            }
            sb.Append("}");
            return sb;
         }
         else if(obj is Hashtable)
         {
            if(hashes.Contains(obj.GetHashCode()))
               return sb.Append("N;");
            else
               hashes.Add(obj.GetHashCode());

            Hashtable a = (Hashtable)obj;
            sb.Append("a:" + a.Count + ":{");
            foreach(DictionaryEntry entry in a)
            {
               sb.Append(serialize(entry.Key));
               sb.Append(serialize(entry.Value));
            }
            sb.Append("}");
            return sb;
         }
         else
         {
            return sb;
         }
      }//Serialize(object obj)

      public object Unserialize(string str)
      {
         pos = 0;
         return unserialize(str);
      }//Unserialize(string str)

      private object unserialize(string str)
      {
         if(str == null || str.Length <= pos)
            return new object();

         int start, end, length;
         string stLen;
         switch(str[pos])
         {
            case 'N':
               pos += 2;
               return null;
            case 'b':
               char chBool;
               chBool = str[pos + 2];
               pos += 4;
               return chBool == '1';
            case 'i':
               string stInt;
               start = str.IndexOf(":", pos) + 1;
               end = str.IndexOf(";", start);
               stInt = str.Substring(start, end - start);
               pos += 3 + stInt.Length;
               return Int32.Parse(stInt);
            case 'd':
               string stDouble;
               start = str.IndexOf(":", pos) + 1;
               end = str.IndexOf(";", start);
               stDouble = str.Substring(start, end - start);
               pos += 3 + stDouble.Length;
               return Double.Parse(stDouble);               
            case 's':
               //TODO: add bounds checking code
               start = str.IndexOf(":", pos) + 1;
               end = str.IndexOf(":", start);
               stLen = str.Substring(start, end - start);
               length = Int32.Parse(stLen);
               pos += 6 + stLen.Length + length;
               string stRet = str.Substring(end + 2, length);
               if(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(":", 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);
               pos += 4 + stLen.Length; //a:Len:{
               for(int i = 0; i < length; i++)
               {
                  //read key
                  object key = unserialize(str);
                  //read value
                  object val = unserialize(str);

                  if(alRet != null)
                  {
                     if(key is int && (int)key == alRet.Count)
                        alRet.Add(val);
                     else
                        alRet = null;
                  }
                  htRet[key] = val;
               }
               pos++; //skip the }
               if(pos < str.Length && str[pos] == ';')//skipping our old extra array semi-colon bug (er... php's weirdness)
                  pos++;
               if(alRet != null)
                  return alRet;
               else
                  return htRet;
            default:
               return "";
         }//switch
      }//unserialzie(object)

      public void TestSerialize()
      {
         string errors = "";
         if(Serialize(false) != "b:0;")
            errors += "serialize bool failed, ";
         if(Serialize(1) != "i:1;")
            errors += "serialize int failed, ";
         if(Serialize(3.14159) != "d:3.14159;")
            errors += "serialize double failed, ";
         if(Serialize("hello world") != "s:11:\"hello world\";")
            errors += "serialize string failed, ";
         Hashtable ht = new Hashtable();
         ht.Add(0, "zero");
         string target = "a:1:{i:0;s:4:\"zero\";};";
         string result = Serialize(ht);
         if(result != target)
            errors += "serialize array failed, ";

         if(Serialize("hello world") != "s:11:\"hello world\";")
            errors += "serialize string failed, ";
         
         if(errors.Length != 0)
            throw new Exception(errors);
      }

      public void TestUnserialize()
      {
         if(((string)Unserialize("s:11:\"hello world\";")) != "hello world")
            throw new Exception("unserialize failed");
      }

      public void TestComplex()
      {
         string errors = "";

         Hashtable ht = new Hashtable();
         ht.Add(0, false);
         ht.Add(1, 1.5);
         ht.Add(2, "two");
         ht.Add("self", ht);
         
         string result = Serialize(ht);
         Hashtable unht = (Hashtable)Unserialize(result);

         if((bool)unht[0] != false
            || (double)unht[1] != 1.5
            || (string)unht[2] != "two"
            || unht["self"] != null)
            errors += "serialize complex failed, ";
         
         if(errors.Length != 0)
            throw new Exception(errors);
      }
   
   }
Аватара пользователя
Sergion
Админ
 
Сообщения: 116
Зарегистрирован: 20 мар 2009, 20:51
Откуда: Москва

Re: PHP Сериализатор

Сообщение PHPDog2009 18 июл 2010, 13:16

Помоему JSON лучше, да и много языков поддерживает http://www.json.org/ ... serialize/unserialize слишком медленный, особенно, когда работает с большими массивами....
Скажи-ка дядя, ведь не даром
Винда, спалённая пожаром,
Пингвинам отдана?
Изображение
Аватара пользователя
PHPDog2009
Герой Форума
 
Сообщения: 107
Зарегистрирован: 08 май 2009, 10:24
Откуда: Россия
  • Сайт
  • ICQ

Re: PHP Сериализатор

Сообщение Neodrop 18 июл 2010, 13:56

php вообще сам по себе слишком медленный.
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: PHP Сериализатор

Сообщение PHPDog2009 18 июл 2010, 14:11

Neodrop писал(а):php вообще сам по себе слишком медленный.

это точно, и в основном эта медленность из-за автоопределения типов переменных...
Скажи-ка дядя, ведь не даром
Винда, спалённая пожаром,
Пингвинам отдана?
Изображение
Аватара пользователя
PHPDog2009
Герой Форума
 
Сообщения: 107
Зарегистрирован: 08 май 2009, 10:24
Откуда: Россия
  • Сайт
  • ICQ

Re: PHP Сериализатор

Сообщение Sergion 18 июл 2010, 18:14

Ну, тут всё зависит от конкретной задачи и проекта прежде всего :) мое дело поделиться, малоль кому еще пригодится.
Если массивы данных не огромные, то стандартной сериализации более чем достаточно и она удобна в использовании.
Аватара пользователя
Sergion
Админ
 
Сообщения: 116
Зарегистрирован: 20 мар 2009, 20:51
Откуда: Москва


Вернуться в Исходники (Копилка)

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


cron