summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--it.class10
-rw-r--r--it_pipe.class172
2 files changed, 182 insertions, 0 deletions
diff --git a/it.class b/it.class
index 26f9dd7..f8c8553 100644
--- a/it.class
+++ b/it.class
@@ -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];
+}
+
+}