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 == '/'); }