Viewing file: CNode.php (21.79 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
class FileLine { public $_note0; // begin notes public $_note1 = ''; // end notes public $_fid; public $_fline0; public $_fline1;
public function __construct($file_id, $from_line, $to_line, $comment) { $this->_fid = $file_id; $this->_fline0 = $from_line; $this->_fline1 = $to_line; $this->_note0 = $comment; }
public function AddEndComment($note1) { $this->_note1 .= "$note1\n"; }
public function debug_str() { return sprintf("fid=%s from line %s to %s", $this->_fid, $this->_fline0, $this->_fline1); } }
class CNode {
const E_WARN = 1; const E_FATAL = 2; const K_ROOT = '__root__'; const K_EXTRACTED = '__extracted__'; const BM_VAL = 1; const BM_BLK = 2; const BM_INC = 4; const BM_IDX = 8; const BM_MULTI = 16; const BM_ROOT = 32; const BM_HAS_RAW = 64; // block contains raw node const BM_RAW = 128; // raw node, no key, just content const T_ROOT = 32; const T_KV = 1; //key-value pair const T_KB = 2; // key blk const T_KVB = 3; // key-value blk const T_INC = 4; // include const T_RAW = 128; // raw content, no key parsed const KEY_WIDTH = 25; const FLD_TYPE = 1; const FLD_KEY = 2; const FLD_VAL = 3; const FLD_ERR = 4; const FLD_ERRLEVEL = 5; const FLD_PARENT = 6; const FLD_FID = 7; const FLD_FLFROM = 8; const FLD_FLTO = 9; const FLD_ELM = 10; const FLD_PRINTKEY = 11;
private $_type = self::T_KV; private $_k; private $_raw_k; private $_print_k; private $_v = null; //value private $_raw_content = null; // raw content private $_raw_tag = null; private $_e = null; //err private $_errlevel = 0; // 1-Warning, 2-fatal private $_parent = null; private $_fileline; private $_changed; private $_els; // elements
function __construct($key, $val, $type = CNode::T_KV) { $this->_raw_k = $key; $this->_k = DKeywordAlias::NormalizedKey($key); $this->_print_k = $key; $this->_changed = true; $this->_type = $type;
if ($this->_type != CNode::T_KV) { $this->_els = array(); } $this->_v = $val; if ($val != null && ($this->_type & self::BM_VAL == 0)) { $this->_type |= self::BM_VAL; } }
public function AddRawContent($line, &$current_comment) { if ($current_comment != '') { $this->_raw_content .= rtrim($current_comment) . "\n"; $current_comment = ''; } $this->_raw_content .= rtrim($line) . "\n"; }
public function AddRawTag($tag) { $this->_type |= self::BM_HAS_RAW; $this->_raw_content = ''; $this->_raw_tag = $tag; }
public function Get($field) { switch ($field) {
case self::FLD_KEY: return $this->_k; case self::FLD_VAL: return $this->_v; case self::FLD_ERR: return $this->_e; case self::FLD_PARENT: return $this->_parent; case self::FLD_FID: return ($this->_fileline == null) ? '' : $this->_fileline->_fid; case self::FLD_FLFROM: return ($this->_fileline == null) ? '' : $this->_fileline->_fline0; case self::FLD_FLTO: return ($this->_fileline == null) ? '' : $this->_fileline->_fline1; } die("field $field not supported"); }
public function Set($field, $fieldval) { switch ($field) {
case self::FLD_FLTO: $this->_fileline->_fline1 = $fieldval; break; case self::FLD_PRINTKEY: $this->_print_k = $fieldval; break; case self::FLD_TYPE: $this->_type = $fieldval; break; case self::FLD_KEY: $this->_raw_k = $fieldval; $this->_k = DKeywordAlias::NormalizedKey($fieldval); $this->_print_k = $fieldval; break;
default: die("field $field not supported"); } }
public function SetVal($v) { $this->_v = $v; if ($v != null && ($this->_type & self::BM_VAL == 0)) $this->_type |= self::BM_VAL; }
public function AddFlag($flag) { $this->_type |= $flag; }
public function HasFlag($flag) { return ($this->_type & $flag) != 0; }
public function HasVal() { // 0 is valid return ($this->_v !== null && $this->_v !== ''); }
public function SetErr($errmsg, $level = 1) { if ($errmsg != '') { $this->_e .= $errmsg; if ($this->_errlevel < $level) $this->_errlevel = $level; } }
public function HasErr() { return $this->_e != null; }
public function HasFatalErr() { return ($this->_errlevel == self::E_FATAL); }
public function HasChanged() { return $this->_changed; }
public function DupHolder() { // create an empty blk node $holder = new CNode($this->_k, $this->_v, $this->_type); if ($this->_errlevel > 0) { $holder->_e = $this->_e; $holder->_errlevel = $this->_errlevel; } $holder->_changed = $this->_changed; $holder->_fileline = $this->_fileline; return $holder; }
public function MergeUnknown($node) { if ($this->_type != self::T_ROOT && !($this->_type & self::BM_BLK)) { echo "Err, should merge at parent level $node->_k $node->_v \n"; return; }
foreach ($node->_els as $k => $el) { if (isset($this->_els[$k])) { if (is_a($el, 'CNode')) { echo " k = $k \n"; $this->_els[$k]->MergeUnknown($el); } else { foreach ($el as $id => $elm) { if (isset($this->_els[$k][$id])) $this->_els[$k][$id]->MergeUnknown($elm); else $this->AddChild($elm); } } } else { if (is_a($el, 'CNode')) $this->AddChild($el); else $this->_els[$k] = $el; // move array over } } }
public function SetRawMap($file_id, $from_line, $to_line, $comment) { $this->_fileline = new FileLine($file_id, $from_line, $to_line, $comment); $this->_changed = false; }
public function EndBlock(&$cur_comment) { if ($this->_raw_tag != '') { $this->_raw_content .= $cur_comment; if ($this->_raw_content != '') { $child = new CNode($this->_raw_tag, $this->_raw_content, self::T_KV | self::T_RAW); $this->AddChild($child); } else { // backward compatible, mark existing node to raw $child = $this->GetChildren($this->_raw_tag); if ($child != null && is_a($child, 'CNode')) { $child->_type |= self::T_RAW; } } } else { $this->_fileline->AddEndComment($cur_comment); } $cur_comment = ''; }
public function AddChild($child) { if ($this->_type == self::T_KV) { $this->_type = ($this->_v == '') ? self::T_KB : self::T_KVB; } $child->_parent = $this; $k = $child->_k; if (isset($this->_els[$k])) { if (!is_array($this->_els[$k])) { $first_node = $this->_els[$k]; $this->_els[$k] = array(); if ($first_node->_v == null) $this->_els[$k][] = $first_node; else $this->_els[$k][$first_node->_v] = $first_node; } if ($child->_v == null) $this->_els[$k][] = $child; else $this->_els[$k][$child->_v] = $child; } else { $this->_els[$k] = $child; } }
public function AddIncludeChildren($incroot) { if (is_array($incroot->_els)) { foreach ($incroot->_els as $elm) { if (is_array($elm)) { foreach ($elm as $elSingle) { $elSingle->AddFlag(self::BM_INC); $this->AddChild($elSingle); } } else { $elm->AddFlag(self::BM_INC); $this->AddChild($elm); } } } }
public function RemoveChild($key) // todo: key contains : { $key = strtolower($key); unset($this->_els[$key]); }
public function RemoveFromParent() { if ($this->_parent != null) { if (is_array($this->_parent->_els[$this->_k])) { foreach ($this->_parent->_els[$this->_k] as $key => $el) { if ($el == $this) { unset($this->_parent->_els[$this->_k][$key]); return; } } } else unset($this->_parent->_els[$this->_k]); $this->_parent = null; } }
public function HasDirectChildren($key = '') { if ($key == '') return ($this->_els != null && count($this->_els) > 0); else return ($this->_els != null && isset($this->_els[strtolower($key)])); }
public function GetChildren($key) { $key = strtolower($key); if (($pos = strpos($key, ':')) > 0) { $node = $this; $keys = explode(':', $key); foreach ($keys as $k) { if (isset($node->_els[$k])) $node = $node->_els[$k]; else return null; } return $node; } elseif (isset($this->_els[$key])) return $this->_els[$key]; // can be array else return null; }
public function GetChildVal($key) { $child = $this->GetChildren($key); return ($child == null || !is_a($child, 'CNode')) ? null : $child->_v; }
public function SetChildVal($key, $val) { $child = $this->GetChildren($key); if ($child == null && !is_a($child, 'CNode')) return false; $child->SetVal($val); return true; }
public function SetChildErr($key, $err) { $child = $this->GetChildren($key); if ($child == null && !is_a($child, 'CNode')) return false; if ($err == null) // clear err $child->SetErr(null, 0); else $child->SetErr($err); return true; }
public function GetChildNodeById($key, $id) { $layer = $this->GetChildren($key); if ($layer != null) { if (is_array($layer)) { return isset($layer[$id]) ? $layer[$id] : null; } elseif ($layer->_v == $id) return $layer; } return null; }
private function get_last_layer($location) { $layers = explode(':', $location); $lastlayer = array_pop($layers); if ($lastlayer != null) { $lastlayer = ltrim($lastlayer, '*'); if (($varpos = strpos($lastlayer, '$')) > 0) { $lastlayer = substr($lastlayer, 0, $varpos); } } return $lastlayer; }
public function GetChildrenByLoc(&$location, &$ref) { $node = $this; if ($location == '') return $node;
$layers = explode(':', $location); foreach ($layers as $layer) { $ismulti = false; if ($layer[0] == '*') { $layer = ltrim($layer, '*'); $ismulti = true; } if (($varpos = strpos($layer, '$')) > 0) { $layer = substr($layer, 0, $varpos); } $location = substr($location, strpos($location, $layer)); $layer = strtolower($layer); if (!isset($node->_els[$layer])) { if ($ismulti && ($ref == '~')) { // for new child, return parent return $node; } else { return null; } }
$nodelist = $node->_els[$layer]; if ($ismulti) { if ($ref == '') return $nodelist;
if ($ref == '~') { // for new child, return parent return $node; }
if (($pos = strpos($ref, '`')) > 0) { $curref = substr($ref, 0, $pos); $ref = substr($ref, $pos + 1); } else { $curref = $ref; $ref = ''; }
if (is_array($nodelist)) { if (!isset($nodelist[$curref])) { return null; } $node = $nodelist[$curref]; } else { $node = $nodelist; if ($node->_v != $curref) { return null; } } } else $node = $nodelist; } return $node; }
public function GetChildNode(&$location, &$ref) { $node = $this->GetChildrenByLoc($location, $ref); return is_a($node, 'CNode') ? $node : null; }
public function UpdateChildren($loc, $curref, $extractData) { $location = $loc; $ref = $curref; $child = $this->GetChildNode($location, $ref); if ($child == null) { // need original loc $child = $this->AllocateLayerNode($loc); } elseif (!is_a($child, 'CNode')) { die("child is not cnode \n"); }
if ($ref == '~') { // new node, ref & location has been modified by GetChildNode // right now, only last one $lastlayer = $this->get_last_layer($loc); $extractData->Set(CNode::FLD_KEY, $lastlayer); $child->AddChild($extractData); } else { foreach ($extractData->_els as $key => $exchild) { if (isset($child->_els[$key])) { unset($child->_els[$key]); } if (is_array($exchild)) { foreach ($exchild as $exchildSingle) { $child->AddChild($exchildSingle); } } else { $child->AddChild($exchild); } } if ($extractData->_v != null && $extractData->_v !== $child->_v) { $child->update_holder_val($extractData->_v); } } }
private function update_holder_val($val) { if ($this->_parent != null) { $oldval = $this->_v; $this->_v = $val; if (is_array($this->_parent->_els[$this->_k])) { unset($this->_parent->_els[$this->_k][$oldval]); $this->_parent->_els[$this->_k][$val] = $this; } } }
public function debug_str() { $buf = ''; $this->debug_out($buf); return $buf; }
public function debug_out(&$buf, $level = 0) { $indent = str_pad('', $level * 2); $buf .= "key={$this->_k} val= {$this->_v} type={$this->_type} "; if ($this->_els != null) { $buf .= " {\n"; $level ++; foreach ($this->_els as $k => $el) { $buf .= "$indent [$k] => "; if (is_array($el)) { $buf .= "\n"; $level ++; foreach ($el as $k0 => $child) { $buf .= "$indent [$k0] => "; if (!is_a($child, 'CNode')) { $buf .= "not cnode "; } $child->debug_out($buf, $level); } } else $el->debug_out($buf, $level); } $buf .= "$indent }\n"; } else $buf .= "\n"; }
public function PrintBuf(&$buf, $level = 0) { $note0 = ($this->_fileline == null) ? '' : $this->_fileline->_note0; $note1 = ($this->_fileline == null) ? '' : $this->_fileline->_note1; $key = $this->_print_k; $alias_note = ''; if (($key1 = DKeywordAlias::GetShortPrintKey($this->_k)) != null) { $key = $key1; if ($note0 == '' && $key != $this->_raw_k) { $alias_note = "# $key is shortened alias of $this->_print_k \n"; } }
if ($note0 != '') $buf .= str_replace("\n\n", "\n", $note0);
if ($this->_errlevel > 0) $buf .= "#__ERR__({$this->_errlevel}): $this->_e \n";
if ($this->_type & self::BM_IDX) return; // do not print index node
if (($this->_type != self::T_INC) && ($this->_type & self::BM_INC)) return; // do not print including nodes
if ($this->_type & self::BM_RAW) { $buf .= rtrim($this->_v) . "\n"; return; } $indent = str_pad('', $level * 2); $val = $this->_v; if ($val != '' && strpos($val, "\n")) { $val = "<<<END_{$key}\n$val\n{$indent}END_{$key}\n"; }
if (($this->_type & self::BM_VAL) && !($this->_type & self::BM_BLK)) { // do not print empty value if ($val != '' || $note0 != '' || $this->_errlevel > 0) { $width = self::KEY_WIDTH - $level * 2; $buf .= $alias_note; $buf .= $indent . str_pad($key, $width) . " $val\n"; } } else { $begin = ''; $end = ''; $buf1 = ''; $buf2 = '';
if ($this->_type & self::BM_BLK) { if ($note0 == '') $buf1 .= "\n"; $buf1 .= $alias_note; $buf1 .= "{$indent}$key $val"; $begin = " {\n"; $end = "$indent}\n"; $level ++; } elseif ($this->_type == self::T_INC) { $buf1 .= "{$indent}$key $val\n"; $buf1 .= "\n##__INC__\n"; $end = "\n##__ENDINC__\n"; }
foreach ($this->_els as $el) { if (is_array($el)) { foreach ($el as $child) $child->PrintBuf($buf2, $level); } else $el->PrintBuf($buf2, $level); }
if ($note1 != '') { $buf2 .= str_replace("\n\n", "\n", $note1); }
// do not print empty block
if ($val != '' || $buf2 != '') { if ($buf2 == '') $buf .= $buf1 . "\n"; else $buf .= $buf1 . $begin . $buf2 . $end; } } }
public function PrintXmlBuf(&$buf, $level = 0) { if ($this->_type == self::T_ROOT) { $buf .= '<?xml version="1.0" encoding="UTF-8"?>' . "\n"; } $indent = str_pad('', $level * 2);
$key = $this->_print_k; $value = htmlspecialchars($this->_v);
if (($this->_type & self::BM_VAL) && !($this->_type & self::BM_BLK)) { if ($value !== '') $buf .= "$indent<$key>$value</$key>\n"; } else { $buf1 = ''; $buf2 = '';
if ($this->_type & self::BM_BLK) { $buf1 .= "$indent<$key>\n"; $level ++; } foreach ($this->_els as $el) { if (is_array($el)) { foreach ($el as $child) $child->PrintXmlBuf($buf2, $level); } else $el->PrintXmlBuf($buf2, $level); }
// do not print empty block if ($buf2 != '') { $buf .= $buf1 . $buf2; if ($this->_type & self::BM_BLK) { $buf .= "$indent</$key>\n"; } } } }
public function LocateLayer($location) { $node = $this; if ($location != '') { $layers = explode(':', $location); foreach ($layers as $layer) { $holder_index = ''; if ($layer[0] == '*') $layer = ltrim($layer, '*'); $varpos = strpos($layer, '$'); if ($varpos > 0) { $holder_index = substr($layer, $varpos + 1); $layer = substr($layer, 0, $varpos); } $children = $node->GetChildren($layer); if ($children == null) return null;
$node = $children; } } return $node; }
public function AllocateLayerNode($location) { $node = $this; if ($location != '') { $layers = explode(':', $location); foreach ($layers as $layer) { if ($layer[0] == '*') { // contains multiple items, return parent node return $node; }
$varpos = strpos($layer, '$'); if ($varpos > 0) { $key = substr($layer, 0, $varpos); $type = CNode::T_KVB; } else { $key = $layer; $type = CNode::T_KB; } $children = $node->GetChildren($key); if ($children == null) { $children = new CNode($key, null, $type); $node->AddChild($children); } $node = $children; } } return $node; }
}
|