add Diogenes_Tree_Node class
[diogenes.git] / include / Tree / Node.php
CommitLineData
55d2e17d
JL
1<?php
2/*
3 * Copyright (C) 2003-2004 Polytechnique.org
4 * http://opensource.polytechnique.org/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21define('NODE_DUMP_BINARY', 0);
22define('NODE_DUMP_TEXT', 1);
23define('NODE_DUMP_NOCHILDREN', 2);
24define('VAR_TYPE_NULL', 0);
25define('VAR_TYPE_INT', 1);
26define('VAR_TYPE_STRING', 2);
27define('VAR_TYPE_ARRAY', 3);
28define('VAR_TYPE_NODE', 4);
29
30function var_encode_text($var, $level = 0, $no_children = FALSE, $tabstr = ' ', $eol = "\n")
31{
32 if (is_object($var) && (get_class($var) == 'Diogenes_Tree_Node')) {
33 // node name
34 $code = str_repeat($tabstr, $level) . "node : {$var->name}" . $eol;
35
36 // encode this node's data
37 $code .= str_repeat($tabstr, $level+1) . "* data : " . var_encode_text($var->data, $level + 2, $no_children, $tabstr, $eol). $eol;
38
39 // encode this node's children
40 if (!$no_children)
41 {
42 $code .= str_repeat($tabstr, $level+1) . "* children" . $eol;
43 foreach ($var->children as $index => $child)
44 $code .= str_repeat($tabstr, $level+2) . "index : $index" . $eol;
45 $code .= var_encode_text($child, $level+2, $no_children, $tabstr, $eol);
46 }
47 return $code;
48 } elseif (is_array($var)) {
49 $arraysep = ",$eol";
50 $code = "array(".$eol;
51 foreach ($var as $key => $value) {
52 $code .= str_repeat($tabstr, $level + 1);
53 $code .= "'$key'=>".var_encode_text($value, $level + 1, $no_children, $tabstr, $eol);
54 $code .= $arraysep;
55 }
56 if (substr($code, -strlen($arraysep)))
57 $code = substr($code, 0, - strlen($arraysep));
58 $code .= $eol;
59 //$code = chop($code, ','); //remove unnecessary coma
60 $code .= str_repeat($tabstr, $level) . ")";
61 return $code;
62 } elseif (is_string($var)) {
63 return "'".$var."'";
64 } elseif (is_bool($var)) {
65 return ($code ? 'TRUE' : 'FALSE');
66 } else {
67 return 'NULL';
68 }
69}
70
71function var_encode_bin($var, $no_children = FALSE)
72{
73 if (is_object($var) && (get_class($var) == 'Diogenes_Tree_Node')) {
74 $code = pack('C', VAR_TYPE_NODE);
75 $code .= var_encode_bin($var->name);
76 $code .= var_encode_bin($var->data);
77 if ($no_children)
78 $code .= var_encode_bin(array());
79 else
80 $code .= var_encode_bin($var->children);
81 } elseif (is_array($var)) {
82 $code = pack('C', VAR_TYPE_ARRAY);
83 $contents = '';
84 foreach ($var as $key => $value) {
85 $contents .= var_encode_bin($key);
86 $contents .= var_encode_bin($value);
87 }
88 $code .= pack('L', strlen($contents));
89 $code .= $contents;
90 } elseif (is_scalar($var)) {
91 $str = "$var";
92 $code = pack('C', VAR_TYPE_STRING);
93 $code .= pack('L', strlen($str));
94 $code .= $str;
95 } else {
96 $code = pack('C', VAR_TYPE_NULL);
97 }
98 return $code;
99}
100
101function var_decode_bin(&$bin)
102{
103 list(,$type) = unpack('C', $bin);
104 $bin = substr($bin, 1);
105 if ($type == VAR_TYPE_NODE)
106 {
107 $name = var_decode_bin($bin);
108 $data = var_decode_bin($bin);
109 $children = var_decode_bin($bin);
110 $var = new Diogenes_Tree_Node($data, $name, $children);
111 } elseif ($type == VAR_TYPE_ARRAY)
112 {
113 list(,$length) = unpack('L', $bin);
114 $bin = substr($bin, 4);
115 $contents = substr($bin, 0, $length);
116 $bin = substr($bin, $length);
117
118 $var = array();
119 while(strlen($contents)) {
120 $key = var_decode_bin($contents);
121 $var[$key] = var_decode_bin($contents);
122 }
123 } elseif ($type == VAR_TYPE_STRING) {
124 list(,$length) = unpack('L', $bin);
125 $bin = substr($bin, 4);
126 $var = substr($bin, 0, $length);
127 $bin = substr($bin, $length);
128 } elseif ($type == VAR_TYPE_NULL) {
129 $var = NULL;
130 } else {
131 trigger_error("unknown type in var_decode_bin : ". $type);
132 }
133 return $var;
134}
135
136/** This class describes Diogenes' plugins.
137 */
138class Diogenes_Tree_Node
139{
140 /** Data for the current node */
141 var $data;
142
143 /** Name for the current node */
144 var $name;
145
146 /** An array of child nodes */
147 var $children = array();
148
149 /** The parent of this node */
150 // var $parent;
151
152 /** Construct a new tree node.
153 */
154 function Diogenes_Tree_Node($data, $name = '', $children=array())
155 {
156 $this->data = $data;
157 $this->name = $name;
158 $this->children = $children;
159 }
160
161 /** Add a child for this node.
162 */
163 function pushChild($node, $index)
164 {
165 array_push($this->children, $node);
166 }
167
168 /** Return the specified child of this node.
169 */
170 function getChild($index)
171 {
172 return $this->children[$index];
173 }
174
175 /** Assign the specified child of this node.
176 */
177 function setChild($index, $node)
178 {
179 $this->children[$index] = $node;
180 }
181
182 /** Read a dump of a node and its children.
183 */
184 function readFile($filename)
185 {
186 $bin = file_get_contents($filename);
187 $node = var_decode_bin($bin);
188 if (!is_object($node) || get_class($node) != 'Diogenes_Tree_Node')
189 {
190 trigger_error('readFile : not a Diogenes_Tree_Node', E_USER_ERROR);
191 }
192 return $node;
193 }
194
195 /** Write a dump of this node and its children.
196 */
197 function writeFile($filename, $mode = NODE_DUMP_IO)
198 {
199 if (!$fp = fopen($filename, "w")) {
200 trigger_error("writeFile : failed to open '$cachefile' for writing", E_USER_ERROR);
201 }
202
203 if ($mode & NODE_DUMP_TEXT) {
204 $out = var_encode_text($this, $level, ($mode & NODE_DUMP_NOCHILDREN));
205 } else {
206 $out = var_encode_bin($this, ($mode & NODE_DUMP_NOCHILDREN));
207 }
208 fputs($fp, $out);
209
210 fclose($fp);
211 }
212
213}
214
215?>