0xDEADBEEF

RSS odkazy english edition

compact-class.php

9. 6. 2013
// 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;
  }
}
píše k47 (@kaja47, k47)