diff options
-rw-r--r-- | it.class | 10 | ||||
-rw-r--r-- | it_pipe.class | 172 |
2 files changed, 182 insertions, 0 deletions
@@ -783,6 +783,16 @@ static function file_put($filename, $data, $p = array()) return ($out = fopen($filename == "-" ? "php://stdout" : $filename, "w")) && (fputs($out, $data) === strlen($data)) && fclose($out); } +function cat($fn) +{ + return new it_pipe(array('fn' => $fn)); +} + +function pipe($cmd, $args = array()) +{ + return new it_pipe(is_string($cmd) ? array('cmd' => $cmd, 'args' => $args) : array('data' => $cmd)); +} + } ?> diff --git a/it_pipe.class b/it_pipe.class new file mode 100644 index 0000000..b3c9d39 --- /dev/null +++ b/it_pipe.class @@ -0,0 +1,172 @@ +<?php + +class it_pipe implements Iterator +{ + +/** + * Creates a pipe object from input. Named arguments: + * $p['fn'] filename to read lines from + * $p['cmd'] cmd to read lines from + * $p['data'] data to read line from. either array of lines without newslines or string + */ +function __construct($p = array()) +{ + if ($p['data']) + $this->lines = $p['data']; + else + $this->lines = isset($p['fn']) ? file($p['fn'], FILE_IGNORE_NEW_LINES) : explode("\n", rtrim(it::exec($p['cmd'], $p['args']))); +} + +/** + * Apply an expression to every line + */ +function map($expr) +{ + $this->lines = it::map($expr, $this->lines); + + return $this; +} + +/** + * Convert pipe from utf8 to iso-latin + */ +function latin() +{ + return $this->map('utf8_decode($v)'); +} + +/** + * Convert pipe from iso-latin to uft8 + */ +function utf8() +{ + return $this->map('utf8_encode($v)'); +} + +/** + * Return contents of pipe as key->val pair (key must be tab separated) + */ +function keyval() +{ + foreach ($this->lines as $line) + { + list($key, $val) = explode("\t", $line, 2); + $result[$key] = $val; + } + + return $result; +} + +/** + * Swap first two columns + */ +function swap() +{ + foreach ($this->lines as $idx => $line) + { + list($col1, $col2) = explode("\t", $line, 2); + $this->lines[$idx] = "$col2\t$col1"; + } + + return $this; +} + +function ED() +{ + ED($this->lines); + + return $this; +} + +function cols($collist) +{ + $keys = explode(",", $collist); + foreach ($this->lines as $idx => $line) + $this->lines[$idx] = (object)array_combine($keys, explode("\t", $line)); + + return $this; +} + +/** + * Return contents of pipe as associative records + */ +function csv() +{ + $schema = explode("\t", it::replace(array('"' => ''), trim(array_shift($this->lines), "#\n"))); + + $oldlocale = setlocale(LC_CTYPE, 'de_CH.iso-8859-1'); + + foreach ($this->lines as $line) + $records[] = (object)array_combine($schema, str_getcsv($line, "\t", '"')); # could do a function_exists('str_getcsv') here... + + setlocale(LC_CTYPE, $oldlocale); + + return $records; +} + +function pipe($cmd) +{ + $descriptors = array(0 => array("pipe", "r"), 1 => array("pipe", "w")); + $process = proc_open($cmd, $descriptors, $pipes); + + fwrite($pipes[0], join("\n", $this->lines) . ($this->lines ? "\n" :"")); + fclose($pipes[0]); + + $this->lines = explode("\n", rtrim(stream_get_contents($pipes[1]))); + $this->key = 0; + fclose($pipes[1]); + proc_close($process); + + return $this; +} + +# +# Magic functions +# +function __call($name, $params) +{ + array_unshift($params, ""); + $func = ($t = it::match('(\w+)__(\w+)', $name)) ? array($t[0], $t[1]) : (method_exists($this, $name) ? array($this, $name) : $name); + + foreach($this->lines as $i => $params[0]) + $this->lines[$i] = call_user_func_array($func, $params); + + return $this; +} + +function __toString() +{ + return is_array($this->lines) ? join("\n", $this->lines) . "\n" : ""; +} + + +# +# Internal: Implement iterator +# +function rewind() +{ + reset($this->lines); + $this->next(); +} + +function next() +{ + $this->valid = each($this->lines); +} + +function valid() +{ + return $this->valid; +} + +function current() +{ + return $this->valid[1]; +} + +function key() +{ + return $this->valid[0]; +} + +} |