360 lines
7.0 KiB
PHP
360 lines
7.0 KiB
PHP
|
<?php
|
||
|
|
||
|
class gmeStrictPropsObject
|
||
|
{
|
||
|
function getTextPropsList()
|
||
|
{
|
||
|
return implode(", ", gme_get_public_props_names($this));
|
||
|
}
|
||
|
|
||
|
function __get($name)
|
||
|
{
|
||
|
throw new Exception("No such property '$name' in class " . get_class($this) . " to get, available properties: " .
|
||
|
$this->getTextPropsList());
|
||
|
}
|
||
|
|
||
|
function __set($name, $value)
|
||
|
{
|
||
|
throw new Exception("No such property '$name' in class " . get_class($this) . " to set, available properties: " .
|
||
|
$this->getTextPropsList());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class gmeDirtableObject extends gmeStrictPropsObject
|
||
|
{
|
||
|
private $__dirty_props = array();
|
||
|
|
||
|
function get($name)
|
||
|
{
|
||
|
return $this->$name;
|
||
|
}
|
||
|
|
||
|
function set($name, $value)
|
||
|
{
|
||
|
$old_value = $this->$name;
|
||
|
|
||
|
//no need to update the property which has the same value
|
||
|
//also comparing long strings can be slow
|
||
|
if(!is_string($value) && $value === $old_value)
|
||
|
return;
|
||
|
|
||
|
$this->$name = $value;
|
||
|
$this->__dirty_props[$name] = 1;
|
||
|
}
|
||
|
|
||
|
function isDirty()
|
||
|
{
|
||
|
return sizeof($this->__dirty_props) > 0;
|
||
|
}
|
||
|
|
||
|
function isDirtyProp($name)
|
||
|
{
|
||
|
return isset($this->__dirty_props[$name]);
|
||
|
}
|
||
|
|
||
|
function getDirtyProps()
|
||
|
{
|
||
|
return $this->__dirty_props;
|
||
|
}
|
||
|
|
||
|
function undirty()
|
||
|
{
|
||
|
$this->__dirty_props = array();
|
||
|
}
|
||
|
|
||
|
function importPublic(array $props)
|
||
|
{
|
||
|
foreach($props as $key => $value)
|
||
|
$this->set($key, $value);
|
||
|
}
|
||
|
|
||
|
function exportPublic()
|
||
|
{
|
||
|
return gme_get_public_props($this);
|
||
|
}
|
||
|
|
||
|
protected function _markDirtyProp($name)
|
||
|
{
|
||
|
$this->__dirty_props[$name] = 1;
|
||
|
}
|
||
|
|
||
|
protected function _unmarkDirtyProp($name)
|
||
|
{
|
||
|
unset($this->__dirty_props[$name]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function gme_get_exception_error(Exception $e, $full_trace = true)
|
||
|
{
|
||
|
return $e->getMessage() . ',' . ($full_trace ? $e->getTraceAsString() : gme_get_exception_short_trace($e));
|
||
|
}
|
||
|
|
||
|
function gme_get_exception_short_trace(Exception $e)
|
||
|
{
|
||
|
$trace = $e->getTrace();
|
||
|
if(!is_array($trace) || !isset($trace[0]) || !isset($trace[0]['file']) || !isset($trace[0]['line']))
|
||
|
return '???(???)';
|
||
|
return $trace[0]['file'] . '(' . $trace[0]['line'] . ')';
|
||
|
}
|
||
|
|
||
|
function gme_q($str)
|
||
|
{
|
||
|
return $str ? '"'.$str.'"' : $str;
|
||
|
}
|
||
|
|
||
|
function gme_get_public_props_names($obj)
|
||
|
{
|
||
|
static $cache = array();
|
||
|
$klass = is_string($obj) ? $obj : get_class($obj);
|
||
|
if(!isset($cache[$klass]))
|
||
|
$cache[$klass] = array_keys(get_class_vars($klass));
|
||
|
return $cache[$klass];
|
||
|
}
|
||
|
|
||
|
function gme_get_public_props($obj)
|
||
|
{
|
||
|
return get_object_vars($obj);
|
||
|
}
|
||
|
|
||
|
function gme_copy_public_props($src, $dst)
|
||
|
{
|
||
|
$props = gme_get_public_props_names($src);
|
||
|
foreach($props as $p)
|
||
|
$dst->$p = $src->$p;
|
||
|
}
|
||
|
|
||
|
function gme_props_arr2flat_arr(array $arr, array $order_props)
|
||
|
{
|
||
|
$flat = array();
|
||
|
foreach($order_props as $p)
|
||
|
$flat[] = $arr[$p];
|
||
|
return $flat;
|
||
|
}
|
||
|
|
||
|
function gme_flat_arr2props_arr(array $flat_arr, array $props)
|
||
|
{
|
||
|
$arr = array();
|
||
|
foreach($props as $i => $p)
|
||
|
$arr[$p] = $flat_arr[$i];
|
||
|
return $arr;
|
||
|
}
|
||
|
|
||
|
function gme_compare_arrays(array $arr1, array $arr2)
|
||
|
{
|
||
|
if(sizeof($arr1) !== sizeof($arr2))
|
||
|
return false;
|
||
|
foreach($arr1 as $idx => $f1)
|
||
|
if($arr2[$idx] !== $f1)
|
||
|
return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
function gme_crc32f($what)
|
||
|
{
|
||
|
//NOTE: making sure that crc32 is always an unsigned value,
|
||
|
//even on 32 bit platform, this is achieved by converting the int
|
||
|
//to float
|
||
|
$v = crc32($what);
|
||
|
if(0 > $v)
|
||
|
$v += 0x100000000;
|
||
|
return floatval($v);
|
||
|
}
|
||
|
|
||
|
function gme_crc28($what)
|
||
|
{
|
||
|
return crc32($what) & 0xFFFFFFF;
|
||
|
}
|
||
|
|
||
|
function gme_static_hash($whar)
|
||
|
{
|
||
|
$hash = 0;
|
||
|
for($i = 0; $i < strlen($whar); ++$i)
|
||
|
{
|
||
|
$hash = ((65599 * $hash) & 0x0FFFFFFF) + ord($whar[$i]);
|
||
|
}
|
||
|
|
||
|
return ($hash ^ ($hash >> 16));
|
||
|
}
|
||
|
|
||
|
function gme_crc16($what)
|
||
|
{
|
||
|
return crc32($what) & 0xFFFF;
|
||
|
}
|
||
|
|
||
|
function gme_pack_array($fmt, array $args)
|
||
|
{
|
||
|
array_unshift($args, $fmt . sizeof($args));
|
||
|
return call_user_func_array('pack', $args);
|
||
|
}
|
||
|
|
||
|
function gme_unpack_array($fmt, $binstr)
|
||
|
{
|
||
|
return unpack("$fmt*", $binstr);
|
||
|
}
|
||
|
|
||
|
function gme_pack_int_array(array $arr)
|
||
|
{
|
||
|
return gme_pack_array('L', $arr);
|
||
|
}
|
||
|
|
||
|
function gme_unpack_int_array($bin)
|
||
|
{
|
||
|
return gme_unpack_array('L', $bin);
|
||
|
}
|
||
|
|
||
|
function gme_pack_map($kfmt, $fmt, array $map)
|
||
|
{
|
||
|
$arr = array();
|
||
|
foreach($map as $k => $v)
|
||
|
{
|
||
|
$arr[] = $k;
|
||
|
$arr[] = $v;
|
||
|
}
|
||
|
|
||
|
return gme_pack_array($fmt, $arr);
|
||
|
}
|
||
|
|
||
|
function gme_unpack_map($kfmt, $fmt, $binstr)
|
||
|
{
|
||
|
$map = array();
|
||
|
$arr = gme_unpack_array($fmt, $binstr);
|
||
|
|
||
|
//unpack for some reason start indices from 1
|
||
|
for($i=1;$i<=sizeof($arr);$i+=2)
|
||
|
{
|
||
|
$map[$arr[$i]] = $arr[$i+1];
|
||
|
}
|
||
|
|
||
|
return $map;
|
||
|
}
|
||
|
|
||
|
function gme_pack_int_map(array $map)
|
||
|
{
|
||
|
return gme_pack_map('L', 'L', $map);
|
||
|
}
|
||
|
|
||
|
function gme_unpack_int_map($bin)
|
||
|
{
|
||
|
return gme_unpack_map('L', 'L', $bin);
|
||
|
}
|
||
|
|
||
|
function gme_json2array($js)
|
||
|
{
|
||
|
$arr = json_decode($js, true);
|
||
|
if($arr === null)
|
||
|
{
|
||
|
if(function_exists('json_last_error'))
|
||
|
{
|
||
|
switch(json_last_error())
|
||
|
{
|
||
|
case JSON_ERROR_DEPTH:
|
||
|
throw new Exception("Maximum stack depth exceeded: $js");
|
||
|
case JSON_ERROR_CTRL_CHAR:
|
||
|
throw new Exception("Unexpected control character found: $js");
|
||
|
case JSON_ERROR_SYNTAX:
|
||
|
throw new Exception("Syntax error, malformed JSON: $js");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
throw new Exception("Could not parse json string: $js");
|
||
|
}
|
||
|
}
|
||
|
return $arr;
|
||
|
}
|
||
|
|
||
|
function gme_json2array_safe($js)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
return gme_json2array($js);
|
||
|
}
|
||
|
catch(Exception $e)
|
||
|
{
|
||
|
return array();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function gme_clamp($v, $min, $max)
|
||
|
{
|
||
|
return max(min($v, $max), $min);
|
||
|
}
|
||
|
|
||
|
function gme_paginate($total, $step)
|
||
|
{
|
||
|
//pages are returned as an array where each element is in interval [N, Y)
|
||
|
$pages = array();
|
||
|
|
||
|
$steps = (int)($total/$step);
|
||
|
$rest = $total % $step;
|
||
|
|
||
|
for($i=1;$i<=$steps;++$i)
|
||
|
$pages[] = array(($i-1)*$step, $i*$step);
|
||
|
|
||
|
if($rest != 0)
|
||
|
$pages[] = array(($i-1)*$step, ($i-1)*$step + $rest);
|
||
|
|
||
|
return $pages;
|
||
|
}
|
||
|
|
||
|
function gme_paginate_array(array $arr, $limit)
|
||
|
{
|
||
|
$splitted = array();
|
||
|
|
||
|
$pages = gme_paginate(sizeof($arr), $limit);
|
||
|
foreach($pages as $page)
|
||
|
{
|
||
|
$tmp = array();
|
||
|
for($i=$page[0];$i<$page[1];++$i)
|
||
|
$tmp[] = $arr[$i];
|
||
|
$splitted[] = $tmp;
|
||
|
}
|
||
|
return $splitted;
|
||
|
}
|
||
|
|
||
|
function gme_normalize_url($url)
|
||
|
{
|
||
|
$parts = explode('/', $url);
|
||
|
$new = array();
|
||
|
foreach($parts as $part)
|
||
|
{
|
||
|
if($part === '..')
|
||
|
array_pop($new);
|
||
|
else
|
||
|
$new[] = $part;
|
||
|
}
|
||
|
return implode('/', $new);
|
||
|
}
|
||
|
|
||
|
function gme_decrypt($encrypted, $pass, $iv)
|
||
|
{
|
||
|
return openssl_decrypt($encrypted, 'AES256', $pass, false, $iv);
|
||
|
}
|
||
|
|
||
|
function gme_encrypt($data, $pass, $iv)
|
||
|
{
|
||
|
return openssl_encrypt($data, 'AES256', $pass, false, $iv);
|
||
|
}
|
||
|
|
||
|
function gme_millisecs($precision = 6)
|
||
|
{
|
||
|
$utimestamp = microtime(true);
|
||
|
$timestamp = floor($utimestamp);
|
||
|
return round(($utimestamp - $timestamp) * pow(10, $precision));
|
||
|
}
|
||
|
|
||
|
function gme_var_dump($v, $max_len = -1, $whitespace_preserve = true)
|
||
|
{
|
||
|
$str = str_replace("\n", "", var_export($v, true));
|
||
|
if(!$whitespace_preserve)
|
||
|
$str = preg_replace("~\s+~", "", $str);
|
||
|
if($max_len > -1 && strlen($str) > $max_len)
|
||
|
$str = substr($str, 0, $max_len) . '...';
|
||
|
return $str;
|
||
|
}
|
||
|
|
||
|
function gme_is_win()
|
||
|
{
|
||
|
return !(DIRECTORY_SEPARATOR == '/');
|
||
|
}
|