php-vfxapply/plugins/executor/Parser.php

106 lines
3.2 KiB
PHP

<?php
namespace VfxApply\Plugin\Executor;
use VfxApply\Plugin;
use VfxApply\Input;
use VfxApply\Output;
use VfxApply\Preset;
class Parser
{
const STDOUT = 1;
const STDERR = 2;
/** @var array Resources */
protected $streams = [];
/** @var string The expression to match (preg match) */
protected $expression;
/** @var int The stream to watch */
protected $source;
/** @var array Index to name mappings */
protected $names = [];
protected $extractors = [];
public function __construct(array $parser=null, $extractors=null)
{
$_ = function($a,$k,$d=null) { return empty($a[$k])?$d:$a[$k]; };
$this->expression = $_($parser,'regex');
$this->source = $_($parser,'from');
foreach ((array)$parser as $k=>$v) {
if (is_numeric($v)) {
$this->names[$k] = $v;
}
}
if (is_array($extractors))
$this->extractors = $extractors;
}
public function prepareExtractors(Script $script, array $env)
{
foreach ($this->extractors as $i=>$extractor) {
if (array_key_exists('write',$extractor)) {
$write = $this->extractors[$i]['write'];
$write = $script->parseVariable($write, $env);
$this->extractors[$i]['write'] = trim($write,"'");
}
}
}
public function parse(array $streams, callable $callback)
{
$this->streams = $streams;
$match = [ 'stdout' => 1, 'stderr' => 2 ];
$source = $this->source?:'stdout';
foreach ($this->streams as $stream)
stream_set_blocking($stream, false);
while (!feof($this->streams[1])) {
$stdout = fread($this->streams[1],8192);
$stderr = fread($this->streams[2],8192);
$this->parseExtractors($stdout, $stderr);
//($stdout) && printf("OUT: <<%s>>\n", $stdout);
//($stderr) && printf("ERR: <<%s>>\n", $stderr);
if (($stdout && $this->expression) && ($source=='stdout'))
if (preg_match($this->expression, $stdout, $match))
call_user_func($callback, $this->parseNames($match));
if (($stderr && $this->expression) && ($source=='stderr'))
if (preg_match($this->expression, $stderr, $match))
call_user_func($callback, $this->parseNames($match));
usleep(10000);
}
}
protected function parseExtractors($stdout, $stderr)
{
foreach ($this->extractors as $extractor) {
switch ($extractor['from']) {
case 'stdout': $buf = $stdout; break;
case 'stderr': $buf = $stderr; break;
}
if ($buf == "") continue;
$lines = explode("\n", $buf);
foreach ($lines as $line) {
if (preg_match($extractor['regex'], $line)) {
$fo = fopen($extractor['write'], "a+");
fwrite($fo, trim($line)."\n");
fclose($fo);
}
}
}
}
protected function parseNames(array $match)
{
$ret = [];
foreach ($this->names as $k=>$index) {
$ret[$k] = $match[$index];
}
return $ret;
}
}