| 
          
            
            
             
			  文件名:rxdata_library.php <?php   /**  ** PHP RXData 解析库 V1.0  **   ** 本函数库是巨大八爪鱼编写的  ** 使用和转载时请保留此信息  **/    define('MARSHAL_MAJOR', 4);  define('MARSHAL_MINOR', 8);    define('RBT_NIL', '0');  define('RBT_TRUE', 'T');  define('RBT_FALSE', 'F');  define('RBT_FIXNUM', 'i');  define('RBT_EXTENDED', 'e');  define('RBT_UCLASS', 'C');  define('RBT_OBJECT', 'o');  define('RBT_DATA', 'd');  define('RBT_USERDEF', 'u');  define('RBT_USRMARSHAL', 'U');  define('RBT_FLOAT', 'f');  define('RBT_BIGNUM', 'l');  define('RBT_STRING', '"');  define('RBT_REGEXP', '/');  define('RBT_ARRAY', '[');  define('RBT_HASH', '{');  define('RBT_HASH_DEF', '}');  define('RBT_STRUCT', 'S');  define('RBT_MODULE_OLD', 'M'); // 该类型为老版格式,已弃用  define('RBT_CLASS', 'c');  define('RBT_MODULE', 'm');  define('RBT_SYMBOL', ':'); // 符号对象  define('RBT_SYMLINK', ';'); // 链接到符号对象  define('RBT_IVAR', 'I');  define('RBT_LINK', '@'); // 链接到非符号对象    define('ONIG_OPTION_IGNORECASE', 0x01);  define('ONIG_OPTION_EXTEND', 0x02);  define('ONIG_OPTION_MULTILINE', 0x04);    define('SIZEOF_CHAR', 1);  define('SIZEOF_DOUBLE', 8);  define('SIZEOF_INT', 2);  define('SIZEOF_LONG', 4); // 在C语言中,int和long都是4个字节...  define('SIZEOF_LONGLONG', 8);    class RubyClass {      public $name;  }    class RubyModule extends RubyClass {}    class RubyNil {}    class RubyObject {      public $_name = '';      public $_length = 0;      public $_extension = '';      public $_data = array();      public function __get($property) {          if (is_numeric($this->_length)) {              return $this->_data[$property];          } else {              if (isset($this->_data['extension'][$property])) {                  return $this->_data['extension'][$property];              } else if (isset($this->data['base'][$property])) {                  return $this->_data['base'][$property];              } else {                  return NULL;              }          }      }  }    class RubySymbol {      public $name;      public function getMember(RubyObject $obj) {          $member = $this->getMemberName();          return $obj->_data[$member];      }      public function getMemberName() {          if ($this->isMember()) {              return substr($this->name, 1);          } else {              return $this->name;          }      }      // 判断该符号对象是不是一个类的属性名称      public function isMember() {          return ($this->name{0} == '@');      }      public function setMember(RubyObject $obj, $value) {          $member = $this->getMemberName();          $obj->_data[$member] = $value;      }  }    /* 根据文件名打开文件并读取一个项目,返回读取的对象并关闭文件 */  function rxdata_load($filename) {      $file = fopen($filename, 'rb');      if ($file === false) {          return NULL;      }      $data = rxdata_load_one($file);      fclose($file);      return $data;  }    /* 根据文件名打开文件并读取全部项目,通过数组返回后关闭文件 */  function rxdata_load_all($filename) {      $file = fopen($filename, 'rb');      if ($file === false) {          return NULL;      }      $data = array();      while ($obj = rxdata_load_one($file)) {          array_push($data, $obj);      }      return $data;  }    /* 从打开的文件中读取一个项目 */  function rxdata_load_one($file) {      $data = NULL;      if (rxdata_read_header($file)) {          rxdata_reset(); // 移除之前的符号表          $data = rxdata_read($file);      }      return $data;  }          /* 读取文件中接下来的符号对象或符号链接所指向的符号对象,以该符号的名称作为对象名,创建并注册对象,返回所创建的对象 */  function rxdata_prepare_object($file, $has_length = true) {      // 在Ruby中,类名和变量名都是符号,且同名符号只能在内存中存在一次      $sym = rxdata_read_symbol_block($file);      $obj = new RubyObject();      $obj->_name = $sym->name;      if ($has_length) {          $obj->_length = rxdata_read_long($file);      }      rxdata_register_object($obj); // 创建对象后立即注册对象(的引用),以便于之后能够链接到该对象      return $obj;  }    function rxdata_read($file) {      $type = fgetc($file);      switch ($type) {      case RBT_ARRAY:          return rxdata_read_array($file);      case RBT_BIGNUM:          return rxdata_read_bignum($file);      case RBT_CLASS:          return rxdata_read_class($file);      case RBT_EXTENDED:          return rxdata_read_extended($file);      case RBT_FALSE:          return false;      case RBT_FIXNUM:          return rxdata_read_fixnum($file);      case RBT_FLOAT:          return rxdata_read_float($file);      case RBT_HASH:          return rxdata_read_hash($file);      case RBT_HASH_DEF:          return rxdata_read_hash($file, true);      case RBT_IVAR:          return rxdata_read_ivar($file);      case RBT_LINK:          return rxdata_read_link($file);      case RBT_MODULE:          return rxdata_read_module($file);      case RBT_NIL:          return new RubyNil();      case RBT_OBJECT:      case RBT_STRUCT:          return rxdata_read_object($file);      case RBT_REGEXP:          return rxdata_read_regexp($file);      case RBT_TRUE:          return true;      case RBT_STRING:          return rxdata_read_string($file, true);      case RBT_SYMBOL:          return rxdata_read_symbol($file);      case RBT_SYMLINK:          return rxdata_read_symlink($file);      case RBT_UCLASS:          return rxdata_read_uclass($file);      case RBT_USERDEF:          return rxdata_read_userdef($file);      case RBT_USRMARSHAL:          return rxdata_read_usrmarshal($file);      default:          trigger_error(sprintf('文件中0x%x处含有无法识别的Ruby数据类型: \'%s\' (0x%02X)', ftell($file), $type, ord($type)), E_USER_WARNING);          return NULL;      }  }    function rxdata_read_array($file) {      $arr = array();      rxdata_register_object($arr);      $len = rxdata_read_long($file);      for ($i = 0; $i < $len; $i++) {          $arr[$i] = rxdata_read($file);      }      return $arr;  }    /* 从文件中读取一个字节 */  /* 此函数读出来的字节一定是无符号十六进制整数 */  function rxdata_read_byte($file) {      $ch = ord(fgetc($file));      return $ch;  }    function rxdata_read_bignum($file) {      $sign = fgetc($file);      $n = rxdata_read_long($file);      $num = rxdata_read_ulong($file, 2 * $n);      if ($sign == '-') {          $num = -$num;      }      rxdata_register_object($num);      return $num;  }    function rxdata_read_class($file) {      $class = new RubyClass();      rxdata_register_object($class);      $class->name = rxdata_read_string($file);      return $class;  }    function rxdata_read_extended($file) {      $ex = rxdata_read_symbol_block($file);      $obj = rxdata_read($file);      if (is_object($obj)) {          $obj->_extension = $ex->name;          return $obj;      } else {          $package = new RubyObject();          $package->_length = count($obj);          $package->_extension = $ex->name;          $package->_data = $obj;          rxdata_registry_replace($obj, $package); // 重定向连接表中的注册信息          return $package;      }  }    /*  注意:      使用rxdata_read_fixnum读取一个Fixnum对象      使用rxdata_read_long读取任意对象原始二进制数据中的长整数值(例如String对象中表示字符串长度的长整数)  */  function rxdata_read_fixnum($file) {      // 在Ruby Marshal中,Fixnum类型的数据无需注册      return rxdata_read_long($file);  }    function rxdata_read_float($file) {      $str = rxdata_read_string($file);      if (in_array($str, array('nan', 'inf', '-inf'))) {          $data = $str;      } else {          $data = (float)$str;      }      rxdata_register_object($data);      return $data;  }    function rxdata_read_hash($file, $hasDefaultValue = false) {      $len = rxdata_read_long($file);      $hash = array();      if ($hasDefaultValue) {          $obj = array(&$hash);      } else {          $obj = &$hash;      }      rxdata_register_object($obj);      for ($i = 0; $i < $len; $i++) {          $key = rxdata_read($file);          $hash[$key] = rxdata_read($file);      }      if ($hasDefaultValue) {          $obj[1] = rxdata_read($file);      }      return $obj;  }    /* 读取Marshal数据头 */  function rxdata_read_header($file) {      $oldpos = ftell($file);      $a = rxdata_read_byte($file);      $b = rxdata_read_byte($file);      if ($a == MARSHAL_MAJOR && $b == MARSHAL_MINOR) {          return true; // 如果读取成功则返回true,且指针移动到数据头的后面      } else {          fseek($file, $oldpos); // 如果读取失败,则退回到读取前的位置,并返回false          return false;      }  }    function rxdata_read_ivar($file) {      $obj = rxdata_read($file);      $base_len = $obj->_length;      $base_data = $obj->_data;      $obj->_length = rxdata_read_long($file);      $obj->_data = array();            rxdata_read_object($file, $obj);      $obj->_length = array('base' => $base_len, 'extension' => $obj->_length);      $obj->_data = array('base' => $base_data, 'extension' => $obj->_data);      return $obj;  }    /* 链接到字节流中的非符号对象 */  function rxdata_read_link($file) {      $id = rxdata_read_long($file);      return rxdata_fetch_object($id);  }    /* 读取一个经过Ruby Marshal特殊处理的有符号长整数(不含类型标记) */  function rxdata_read_long($file) {      $ch = to_signed(rxdata_read_byte($file));      if ($ch == 0) {          return 0;      }      if ($ch > 0) {          if ($ch > 4 && $ch < 128) {              return $ch - 5;          }          $x = 0;          for ($i = 0; $i < $ch; $i++) {              $x |= to_signed(rxdata_read_byte($file), SIZEOF_LONG) << (8 * $i);          }      } else {          if ($ch > -129 && $ch < -4) {              return $ch + 5;          }          $ch = -$ch;          $x = -1;          for ($i = 0; $i < $ch; $i++) {              $x &= ~(0xff << (8 * $i));              $x |= to_signed(rxdata_read_byte($file), SIZEOF_LONG) << (8 * $i);          }      }      return $x;  }    function rxdata_read_module($file) {      $module = new RubyModule();      rxdata_register_object($module);      $module->name = rxdata_read_string($file);      return $module;  }    // 如果指定了参数$obj,则此函数只读取成员变量  function rxdata_read_object($file, $obj = NULL) {      if (is_null($obj)) {          $obj = rxdata_prepare_object($file);      }      for ($i = 0; $i < $obj->_length; $i++) {          $memsym = rxdata_read_symbol_block($file);          $memsym->setMember($obj, rxdata_read($file, $obj));      }      return $obj;  }    function rxdata_read_regexp($file) {      $reg = '/' . rxdata_read_string($file) . '/';      $options = rxdata_read_byte($file);      if ($options & ONIG_OPTION_IGNORECASE) {          $reg .= 'i';      }      if ($options & ONIG_OPTION_MULTILINE) {          $reg .= 'm';      }      if ($options & ONIG_OPTION_EXTEND) {          $reg .= 'x';      }      rxdata_register_object($reg);      return $reg;  }    function rxdata_read_string($file, $register = false) {      $len = rxdata_read_long($file);      if ($len > 0) {          $str = fread($file, $len);      } else {          $str = '';      }      if ($register) {          rxdata_register_object($str);      }      return $str;  }    function rxdata_read_symbol($file) {      $symbol = new RubySymbol();      $symbol->name = rxdata_read_string($file);      rxdata_register_symbol($symbol); // 注册该符号,以便于之后链接回来。因为在内存中,同名符号对象只允许存在一次      return $symbol;  }  function rxdata_read_symbol_block($file) {      $type = fgetc($file);      if ($type == RBT_SYMBOL) {          return rxdata_read_symbol($file);      } else if ($type == RBT_SYMLINK) {          return rxdata_read_symlink($file);      } else {          return NULL;      }  }  function rxdata_read_symlink($file) {      $id = rxdata_read_long($file);      return rxdata_fetch_symbol($id);  }    function rxdata_read_uclass($file) {      $obj = rxdata_prepare_object($file, false);      $next_registry = count($GLOBALS['_RBOBJLIST']);      $obj->_data = rxdata_read($file);      rxdata_unregister_object($next_registry); // 由于$obj已经注册,所以需要删除重复注册的$obj->_data      $obj->_length = count($obj->_data);      return $obj;  }    /* 获取一个由固定n个字节(小端序)表示的无符号整数 */  function rxdata_read_ulong($file, $n = SIZEOF_LONG) {      $num = 0;      for ($i = 0; $i < $n; $i++) {          $v = rxdata_read_byte($file);          $num += ($v << ($i * 8));      }      return $num;  }    // 注意:由于$obj已经注册,所以返回时必须返回$obj,不能返回其他变量  function rxdata_read_userdef($file) {      $obj = rxdata_prepare_object($file);      switch ($obj->_name) {      case 'Table':          // Table是RGSS自带的内部类,不是Ruby自带的类          // 地图图层的三维数组的结构是: data[x坐标, y坐标, 地图id]          $dim = rxdata_read_ulong($file); // 数组的维数          $xsize = rxdata_read_ulong($file);          $ysize = rxdata_read_ulong($file);          $zsize = rxdata_read_ulong($file);          $total = rxdata_read_ulong($file);                    $arr = array();          for ($i = 0; $i < $total; $i++) {              $value = to_signed(rxdata_read_ulong($file, SIZEOF_INT), SIZEOF_INT);              if ($dim == 1) {                  $arr[$i] = $value;              } else if ($dim == 2) {                  $x = $i % $xsize;                  $y = (int)($i / $xsize);                  if (!isset($arr[$x])) {                      $arr[$x] = array();                  }                  $arr[$x][$y] = $value;              } else if ($dim == 3) {                  $x = $i % $xsize;                  $y = (int)($i % ($xsize * $ysize) / $xsize);                  $z = (int)($i / ($xsize * $ysize));                  if (!isset($arr[$x])) {                      $arr[$x] = array();                  }                  if (!isset($arr[$x][$y])) {                      $arr[$x][$y] = array();                  }                  $arr[$x][$y][$z] = $value;              }          }          $obj->_data = $arr;          break;      case 'Color':      case 'Tone':          $format = 'dred/dgreen/dblue/d';          if ($obj->_name == 'Color') {              $format .= 'alpha';          } else {              $format .= 'gray';          }          $data = fread($file, 4 * SIZEOF_DOUBLE);          $obj->_data = unpack($format, $data);          break;      default:          /* 输出范例:          ** Array ( [0] => RubyObject Object ( [_name] => Color [_length] => 32 [_data] => Array ( ) [data] => 00 00 00 00 00 C0 58 40 00 00 00 00 00 00 59 40 00 00 00 00 00 C0 62 40 00 00 00 00 00 E0 6F 40 ) )           **/          $data = fread($file, $obj->_length);          trigger_error("无法解析的自定义对象类型\"{$obj->_name}\"", E_USER_NOTICE);          $obj->_data = '';          for ($i = 0; $i < $obj->_length; $i++) {              $obj->_data .= sprintf("%02X ", ord($data{$i}));          }          $obj->_data = rtrim($obj->_data);      }      return $obj;  }    function rxdata_read_usrmarshal($file) {      $obj = rxdata_prepare_object($file, false);      $obj->_length = 1;      $obj->_data = rxdata_read($file);      return $obj;  }    /* Ruby链接列表相关函数 */  $_RBOBJLIST = array(); // 当前字节流中出现的所有非符号对象  $_RBSYMLIST = array(); // 当前字节流中出现的所有符号对象    // 获取已注册的非符号对象  function rxdata_fetch_object($id) {      global $_RBOBJLIST;      if (isset($_RBOBJLIST[$id])) {          return $_RBOBJLIST[$id];      } else {          trigger_error(sprintf('引用未注册的非符号对象ID: %d,已注册的最大ID为: %d', $id, count($_RBOBJLIST) - 1), E_USER_WARNING);          return NULL;      }  }    // 获取已注册的符号对象  function rxdata_fetch_symbol($id) {      global $_RBSYMLIST;      if (isset($_RBSYMLIST[$id])) {          return $_RBSYMLIST[$id];      } else {          trigger_error(sprintf('引用未注册的符号对象ID: %d,已注册的最大ID为: %d', $id, count($_RBSYMLIST) - 1), E_USER_WARNING);          return NULL;      }  }    // 注册非符号对象  function rxdata_register_object(&$obj) {      global $_RBOBJLIST;      $id = count($_RBOBJLIST);      $_RBOBJLIST[$id] = &$obj;      return $id;  }    // 注册符号对象  function rxdata_register_symbol(RubySymbol $sym) {      global $_RBSYMLIST;      $id = count($_RBSYMLIST);      $_RBSYMLIST[$id] = $sym; // $sym本身就是一个php对象,所以这里无需加上引用符号      return $id;  }    // 替换非符号对象注册信息  function rxdata_registry_replace(&$old, &$new) {      global $_RBOBJLIST;      foreach ($_RBOBJLIST as $i => $v) {          if ($v === $old) {              $_RBOBJLIST[$i] = &$new;          }      }  }    // 清空上一个字节流的所有链接列表  function rxdata_reset() {      $GLOBALS['_RBOBJLIST'] = array();      $GLOBALS['_RBSYMLIST'] = array();  }    function rxdata_unregister_object($id = NULL) {      global $_RBOBJLIST;      if (is_null($id)) {          // 取消注册最近注册的对象          array_pop($_RBOBJLIST);      } else {          // 取消注册指定序号的对象          unset($_RBOBJLIST[$id]);          $_RBOBJLIST = array_values($_RBOBJLIST);      }  }        /* 将无符号十六进制数转换为有符号十进制整数, 参数$bytes规定了有符号整数类型的字节数 */  /* 在marshal.c中,宏SIGN_EXTEND_CHAR(n)就相当于这里的to_signed(n) */  function to_signed($hex, $bytes = SIZEOF_CHAR) {      $mask = 1 << ($bytes * 8 - 1);      return ($hex ^ $mask) - $mask;  }    /* 将有符号十进制整数转换为无符号十六进制整数 */  function to_unsigned($dex, $bytes = SIZEOF_CHAR) {      $mask = 1 << ($bytes * 8 - 1);      return ($dex + $mask) ^ $mask;  }    // 在64位php中,整数1的十六进制是0x01,而整数-1的十六进制数是0xffffffffffffffff  // 因此,如果想要char a = -1的十六进制值,只需在php中写上-1 & 0xff即可  // echo '0x', dechex(-1 & 0xff); // 输出0xff  // 使用to_unsigned函数也能达到同样的目的: echo to_unsigned(-1, SIZEOF_CHAR);  // 此外,php还提供了unpack函数读取二进制字符串表示的无符号整数             
                       |