Instantly share code, notes, and snippets.

@kaja47 kaja47/gist:5743608
Last active Dec 18, 2015

Embed
What would you like to do?
I'm pretty sure, PHP guys will crucify me for this abomination.
<?php
// 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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment