protected function doInvoke($input, $context)
{
$output = new BytesIO();
$reader = new Reader($input);
do {
$reader->reset();
$name = $reader->readString();
$alias = strtolower($name);
if (isset($this->calls[$alias])) {
$call = $this->calls[$alias];
} elseif (isset($this->calls['*'])) {
$call = $this->calls['*'];
} else {
throw new \Exception("Can't find this function " . $name . "().");
}
$mode = $call->mode;
$simple = $call->simple;
if ($simple === null) {
$simple = $this->simple;
}
$args = array();
$byref = false;
$async = $call->async;
$tag = $input->getc();
if ($tag == Tags::TagList) {
$reader->reset();
$args = $reader->readListWithoutTag();
$tag = $input->getc();
if ($tag == Tags::TagTrue) {
$byref = true;
$tag = $input->getc();
}
if ($call->byref) {
$_args = array();
foreach ($args as $i => &$arg) {
if ($call->params[$i]->isPassedByReference()) {
$_args[] =& $arg;
} else {
$_args[] = $arg;
}
}
$args = $_args;
}
}
if ($tag != Tags::TagEnd && $tag != Tags::TagCall) {
throw new \Exception('Unknown tag: ' . $tag . "\r\n" . 'with following data: ' . $input->toString());
}
if ($this->onBeforeInvoke !== null) {
$beforeInvoke = $this->onBeforeInvoke;
call_user_func_array($beforeInvoke, array($name, &$args, $byref, $context));
}
if (array_key_exists('*', $this->calls) && $call === $this->calls['*']) {
$args = array($name, $args);
}
if ($async) {
$completer = new Completer();
$args[] = array(new AsyncCallback($completer), "handler");
call_user_func_array($call->func, $args);
$result = $completer->future();
} else {
$result = call_user_func_array($call->func, $args);
}
if ($result != null && $result instanceof Future) {
$completer = new Completer();
$callback = new AfterInvokeCallback($this, $completer, $name, $args, $byref, $mode, $simple, $context);
$result->then(array($callback, "handler"))->catchError(array($callback, "errorHandler"));
return $completer->future();
}
$result = $this->afterInvoke($name, $args, $byref, $mode, $simple, $context, $result, $output, false);
if ($result != null) {
return $result;
}
} while ($tag == Tags::TagCall);
$output->write(Tags::TagEnd);
return $this->outputFilter($output->toString(), $context);
}