106 lines
3.2 KiB
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;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|