compact-class.php
9. 6. 2013 #kód
// The only chance now, I felt was the possibility that we'd gone to such // excess that nobody in the position to bring the hammer down on us could // possibly believe it. // Hunter S. Thompson trait CompactClass { private $data; static $compactOffsets = null; static $compactLength = 0; function initCompactClass() { if (self::$compactOffsets === null) { self::$compactOffsets = []; $lengths = [ 'byte' => 1, 'int16' => 2, 'int32' => 4, 'int64' => 8 ]; $offset = 0; foreach (self::$compactFields as $f => $t) { self::$compactOffsets[$f] = $offset; $offset += $lengths[$t]; } self::$compactLength = $offset; } $this->data = str_repeat("\0", self::$compactLength); } function getByte($offset) { return ord($this->data[$offset]); } function putByte($offset, $val) { $this->data[$offset] = chr($val); } function getInt16($offset) { $bytes = substr($this->data, $offset, 2); $res = unpack('v', $bytes); return $res[1]; } function putInt16($offset, $val) { $bytes = pack('v', $val); $this->data[$offset+0] = $bytes[0]; $this->data[$offset+1] = $bytes[1]; } function getInt32($offset) { $bytes = substr($this->data, $offset, 4); $res = unpack('V', $bytes); return $res[1]; } function putInt32($offset, $val) { $bytes = pack('V', $val); $this->data[$offset+0] = $bytes[0]; $this->data[$offset+1] = $bytes[1]; $this->data[$offset+2] = $bytes[2]; $this->data[$offset+3] = $bytes[3]; } function getInt64($offset) { $bytes = substr($this->data, $offset, 8); list(, $a, $b) = unpack('V2', $bytes); return ($a << 32) + $b; } function putInt64($offset, $val) { $a = $val >> 32; $b = $val & 0xffffffff; $bytes = pack('VV', $a, $b); for ($i = 0; $i < 8; $i++) { $this->data[$offset + $i] = $bytes[$i]; } } function __get($key) { if (isset(self::$compactFields[$key])) { $type = self::$compactFields[$key]; $offset = self::$compactOffsets[$key]; $method = "get$type"; return $this->$method($offset); } else { return $this->$key; } } function __set($key, $val) { if (isset(self::$compactFields[$key])) { $type = self::$compactFields[$key]; $offset = self::$compactOffsets[$key]; $method = "put$type"; $this->$method($offset, $val); } else { return $this->$key = $val; } } } // example class Post { use CompactClass; static $compactFields = array( 'no' => 'int32', 'resto' => 'int32', 'time' => 'int32', 'tim' => 'int64', 'fsize' => 'int32', 'w' => 'int16', 'h' => 'int16', 'tn_w' => 'byte', 'tn_h' => 'byte', 'replies' => 'int16', 'images' => 'int16', ); function __construct($data = array()) { $this->initCompactClass(); foreach ($data as $k => $v) $this->$k = $v; } }