process(); $res->normalized_jzon = $normalized_jzon; $res->jsm_module = $jsm_module; } catch(Exception $e) { $res->error = 1; $res->error_descr = $e->getMessage() . "\n" . $e->getTraceAsString(); return $res; } $decode_res = config_check_and_decode_jzon($normalized_jzon); if($decode_res[0] === 0) { $res->parsed_arr = $decode_res[2]; $res->parser_type = $decode_res[3]; } else { $res->error = $decode_res[0]; $res->error_descr = $decode_res[1]; } return $res; } function config_check_and_decode_jzon(string $json) : array { try { $parser = 0; $arr = \jzon_parse($json, $parser); return array(0, "", $arr, $parser); } catch(Exception $e) { return array(1, $e->getMessage(), array(), 0); } } function config_get_header(string $file, ?int &$conf_id, ?string &$strid, bool $use_cache = true) : bool { static $cache = array(); if($use_cache && isset($cache[$file])) { list($conf_id, $strid) = $cache[$file]; return true; } $h = fopen($file, "r"); $line = fgets($h, 256); fclose($h); //TODO: rewrite it without regex usage if(preg_match('~\{\s*/\*\s*proto_id\s*=\s*(\d+)\s*;\s*alias\s*=\s*([^\s]+)~', $line, $matches)) { $conf_id = (int)$matches[1]; $strid = $matches[2]; if($use_cache) $cache[$file] = array($conf_id, $strid); return true; } else return false; } function config_set_header(string $contents, int $conf_id, string $strid, bool &$is_success) : string { $contents = preg_replace('~\s*\{~', "{ /* proto_id = {$conf_id} ; alias = {$strid} */", $contents, 1/*limit*/, $count); $is_success = $count == 1; return $contents; } function config_replace_header(string $contents) : string { return preg_replace('~(\s*\{)\s*/\*\s*proto_id\s*=\s*\d+\s*;\s*alias\s*=\s*[^\s]+\s*\*/~', '$1', $contents); } //returns [proto_id, alias] function config_ensure_header(string $conf_dir, string $file, bool $force = false) : array { if(config_get_header($file, $curr_proto_id, $curr_alias, !$force)) { //TODO: add 'normalized' argument when we are sure both path arguments are normalized $alias = config_file2strid($conf_dir, $file); if($force) $curr_proto_id = config_file2id($conf_dir, $file); //NOTE: keeping current proto id intact if not forced if($force || $curr_alias !== $alias) { $lines = file($file); //TODO: why not using config_set_header(..) ? $lines[0] = preg_replace( '~\s*\{\s*/\*\s*proto_id\s*=\s*\d+\s*;\s*alias\s*=\s*[^\s]+\s*\*/~', "{ /* proto_id = {$curr_proto_id} ; alias = {$alias} */", $lines[0], 1/*limit*/, $count); if($count != 1) throw new Exception("Could not set header for '$file' in line: {$lines[0]}"); ensure_write_if_differs($file, join("", $lines)); } return array($curr_proto_id, $alias); } else { $conf_id = config_file2id($conf_dir, $file); $alias = config_file2strid($conf_dir, $file); $lines = file($file); $is_success = false; $lines[0] = config_set_header($lines[0], $conf_id, $alias, $is_success); if(!$is_success) throw new Exception("Could not set header for '$file' in line: {$lines[0]}"); ensure_write($file, join("", $lines)); return array($conf_id, $alias); } } function config_apply_class_normalization(array $kv_data, bool $check_junk = false) : array { $class = $kv_data['class']; $norm_data = array(); unset($kv_data['class']); call_user_func_array([$class, 'normalize'], array(&$kv_data, &$norm_data, true, $check_junk)); return array($class, $class::CLASS_ID, $norm_data); } //returns array function config_content_match_refs(string $src) : array { $refs = array(); if(strpos($src, '@') === false) return $refs; if(preg_match_all('~"(@[^"]+)"~', $src, $matches)) { foreach($matches[1] as $ref) { if(!isset($refs[$ref])) $refs[$ref] = 1; ++$refs[$ref]; } } return $refs; }