<commit_before><?hh // strict
/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/

/**********************************************************\
 *                                                        *
 * Hprose/Service.hh                                      *
 *                                                        *
 * hprose service library for hack.                       *
 *                                                        *
 * LastModified: Mar 8, 2015                              *
 * Author: Ma Bingyao <andot@hprose.com>                  *
 *                                                        *
\**********************************************************/

namespace Hprose {
    class RemoteCall {
        public array<\ReflectionParameter> $params;
        public bool $byref;
        public function __construct(public mixed $func,
                                    public ResultMode $mode,
                                    public ?bool $simple) {
            if (is_array($func)) {
                $this->params = (new \ReflectionMethod($func[0], $func[1]))->getParameters();
            }
            else {
                $this->params = (new \ReflectionFunction($func))->getParameters();
            }
            $this->byref = false;
            foreach($this->params as $param) {
                if ($param->isPassedByReference()) {
                    $this->byref = true;
                    break;
                }
            }
        }
    }
    abstract class Service {
        private static array<string> $magic_methods = array(
            "__construct",
            "__destruct",
            "__call",
            "__callStatic",
            "__get",
            "__set",
            "__isset",
            "__unset",
            "__sleep",
            "__wakeup",
            "__toString",
            "__invoke",
            "__set_state",
            "__clone"
        );
        private Map<string, RemoteCall> $calls = Map {};
        private Vector<string> $names = Vector {};
        private Vector<Filter> $filters = Vector {};
        private bool $simple = false;
        protected bool $debug = false;
        protected int $error_types = E_ALL & ~E_NOTICE;
        public ?(function(string, array<mixed>, bool, \stdClass): void) $onBeforeInvoke = null;
        public ?(function(string, array<mixed>, bool, mixed, \stdClass): void) $onAfterInvoke = null;
        public ?(function(string, \stdClass): void) $onSendError = null;

        protected function inputFilter(string $data,
                                       \stdClass $context): string {
            $count = count($this->filters);
            for ($i = $count - 1; $i >= 0; $i--) {
                $data = $this->filters[$i]->inputFilter($data, $context);
            }
            return $data;
        }
        protected function outputFilter(string $data,
                                        \stdClass $context): string {
            $count = count($this->filters);
            for ($i = 0; $i < $count; $i++) {
                $data = $this->filters[$i]->outputFilter($data, $context);
            }
            return $data;
        }
        protected function sendError(string $error,
                                     \stdClass $context): string {
            if ($this->onSendError !== null) {
                $sendError = $this->onSendError;
                $sendError($error, $context);
            }
            $stream = new BytesIO();
            $writer = new Writer($stream, true);
            $stream->write(Tags::TagError);
            $writer->writeString($error);
            $stream->write(Tags::TagEnd);
            $data = $stream->toString();
            $stream->close();
            return $this->outputFilter($data, $context);
        }
        protected function doInvoke(BytesIO $input,
                                    \stdClass $context): string {
            $output = new BytesIO();
            $reader = new Reader($input);
            do {
                $reader->reset();
                $name = (string)$reader->readString();
                $alias = strtolower($name);
                if ($this->calls->contains($alias)) {
                    $call = $this->calls[$alias];
                }
                elseif ($this->calls->contains('*')) {
                    $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;
                $tag = $input->getc();
                if ($tag == Tags::TagList) {
                    $reader->reset();
                    $args = $reader->readListWithoutTag()->toArray();
                    $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;
                    $beforeInvoke($name, $args, $byref, $context);
                }
                if ($this->calls->contains('*') &&
                    $call === $this->calls['*']) {
                    $args = array($name, $args);
                }
                $result = call_user_func_array($call->func, $args);
                if ($this->onAfterInvoke !== null) {
                    $afterInvoke = $this->onAfterInvoke;
                    $afterInvoke($name, $args, $byref, $result, $context);
                }
                // some service functions/methods may echo content, we need clean it
                @ob_clean();
                if ($mode == ResultMode::RawWithEndTag) {
                    return $this->outputFilter($result, $context);
                }
                elseif ($mode == ResultMode::Raw) {
                    $output->write($result);
                }
                else {
                    $writer = new Writer($output, $simple);
                    $output->write(Tags::TagResult);
                    if ($mode == ResultMode::Serialized) {
                        $output->write($result);
                    }
                    else {
                        $writer->reset();
                        $writer->serialize($result);
                    }
                    if ($byref) {
                        $output->write(Tags::TagArgument);
                        $writer->reset();
                        $writer->writeArray($args);
                    }
                }
            } while ($tag == Tags::TagCall);
            $output->write(Tags::TagEnd);
            return $this->outputFilter($output->toString(), $context);
        }
        protected function doFunctionList(\stdClass $context): string {
            $stream = new BytesIO();
            $writer = new Writer($stream, true);
            $stream->write(Tags::TagFunctions);
            $writer->writeList($this->names);
            $stream->write(Tags::TagEnd);
            $data = $stream->toString();
            $stream->close();
            return $this->outputFilter($data, $context);
        }
        private static function getDeclaredOnlyMethods(string $class): array<string> {
            $result = get_class_methods($class);
            if ($parent_class = get_parent_class($class)) {
                $inherit = get_class_methods($parent_class);
                $result = array_diff($result, $inherit);
            }
            $result = array_diff($result, self::$magic_methods);
            return $result;
        }
        public function addMissingFunction(mixed $func,
                                       ResultMode $mode = ResultMode::Normal,
                                       ?bool $simple = null): void {
            $this->addFunction($func, '*', $mode, $simple);
        }
        public function addFunction(mixed $func,
                                    string $alias = '',
                                    ResultMode $mode = ResultMode::Normal,
                                    ?bool $simple = null): void {
            if (!is_callable($func)) {
                throw new \Exception('Argument func is not callable.');
            }
            if ($alias == '') {
                if (is_string($func)) {
                    $alias = $func;
                }
                elseif (is_array($func)) {
                    $alias = $func[1];
                }
                else {
                    throw new \Exception('alias must be a string.');
                }
            }
            $name = strtolower($alias);
            if (!$this->calls->contains($name)) {
                $this->names->add($alias);
            }
            $this->calls[$name] = new RemoteCall($func, $mode, $simple);
        }
        public function addFunctions(array<mixed> $funcs,
                                     array<string> $aliases = array(),
                                     ResultMode $mode = ResultMode::Normal,
                                     ?bool $simple = null): void {
            $count = count($aliases);
            if ($count == 0) {
                foreach ($funcs as $func) {
                    $this->addFunction($func, '', $mode, $simple);
                }
            }
            elseif ($count == count($funcs)) {
                foreach ($funcs as $i => $func) {
                    $this->addFunction($func, $aliases[$i], $mode, $simple);
                }
            }
            else {
                throw new \Exception('The count of functions is not matched with aliases');
            }
        }
        public function addMethod(string $methodname,
                                  mixed $belongto,
                                  string $alias = '',
                                  ResultMode $mode = ResultMode::Normal,
                                  ?bool $simple = null): void {
            $func = array($belongto, $methodname);
            $this->addFunction($func, $alias, $mode, $simple);
        }
        public function addMethods(array<string> $methods,
                                   mixed $belongto,
                                   mixed $aliases = '',
                                   ResultMode $mode = ResultMode::Normal,
                                   ?bool $simple = null): void {
            if ($aliases === null || count($aliases) == 0) {
                $aliases = '';
            }
            $_aliases = array();
            if (is_string($aliases)) {
                $aliasPrefix = $aliases;
                if ($aliasPrefix !== '') {
                    $aliasPrefix .= '_';
                }
                foreach ($methods as $k => $method) {
                    $_aliases[$k] = $aliasPrefix . $method;
                }
            }
            elseif (is_array($aliases)) {
                $_aliases = $aliases;
            }
            elseif ($aliases instanceof \Indexish) {
                $_aliases = $aliases;
            }
            if (count($methods) != count($_aliases)) {
                throw new \Exception('The count of methods is not matched with aliases');
            }
            foreach($methods as $k => $method) {
                $func = array($belongto, $method);
                $this->addFunction($func, $_aliases[$k], $mode, $simple);
            }
        }
        public function addInstanceMethods(mixed $object,
                                        string $class = '',
                                        string $aliasPrefix = '',
                                        ResultMode $mode = ResultMode::Normal,
                                        ?bool $simple = null): void {
            if ($class == '') {
                $class = get_class($object);
            }
            $this->addMethods(self::getDeclaredOnlyMethods($class),
                              $object, $aliasPrefix, $mode, $simple);
        }
        public function addClassMethods(string $class,
                                        string $execclass = '',
                                        string $aliasPrefix = '',
                                        ResultMode $mode = ResultMode::Normal,
                                        ?bool $simple = null): void {
            if ($execclass == '') {
                $execclass = $class;
            }
            $this->addMethods(self::getDeclaredOnlyMethods($class),
                              $execclass, $aliasPrefix, $mode, $simple);
        }
        public function add(...): void {
            $args_num = func_num_args();
            $args = func_get_args();
            switch ($args_num) {
                case 1: {
                    if (is_callable($args[0])) {
                        $this->addFunction($args[0]);
                        return;
                    }
                    elseif (is_array($args[0])) {
                        $this->addFunctions($args[0]);
                        return;
                    }
                    elseif (is_object($args[0])) {
                        $this->addInstanceMethods($args[0]);
                        return;
                    }
                    elseif (is_string($args[0])) {
                        $this->addClassMethods($args[0]);
                        return;
                    }
                    break;
                }
                case 2: {
                    if (is_callable($args[0]) && is_string($args[1])) {
                        $this->addFunction($args[0], $args[1]);
                        return;
                    }
                    elseif (is_string($args[0])) {
                        if (is_string($args[1]) && !is_callable(array($args[1], $args[0]))) {
                            if (class_exists($args[1])) {
                                $this->addClassMethods($args[0], $args[1]);
                            }
                            else {
                                $this->addClassMethods($args[0], '', $args[1]);
                            }
                        }
                        else {
                            $this->addMethod($args[0], $args[1]);
                        }
                        return;
                    }
                    elseif (is_array($args[0])) {
                        if (is_array($args[1])) {
                            $this->addFunctions($args[0], $args[1]);
                        }
                        else {
                            $this->addMethods($args[0], $args[1]);
                        }
                        return;
                    }
                    elseif (is_object($args[0])) {
                        $this->addInstanceMethods($args[0], $args[1]);
                        return;
                    }
                    break;
                }
                case 3: {
                    if (is_callable($args[0]) && $args[1] == '' && is_string($args[2])) {
                        $this->addFunction($args[0], $args[2]);
                        return;
                    }
                    elseif (is_string($args[0]) && is_string($args[2])) {
                        if (is_string($args[1]) && !is_callable(array($args[0], $args[1]))) {
                            $this->addClassMethods($args[0], $args[1], $args[2]);
                        }
                        else {
                            $this->addMethod($args[0], $args[1], $args[2]);
                        }
                        return;
                    }
                    elseif (is_array($args[0])) {
                        if ($args[1] == '' && is_array($args[2])) {
                            $this->addFunctions($args[0], $args[2]);
                        }
                        else {
                            $this->addMethods($args[0], $args[1], $args[2]);
                        }
                        return;
                    }
                    elseif (is_object($args[0])) {
                        $this->addInstanceMethods($args[0], $args[1], $args[2]);
                        return;
                    }
                    break;
                }
                throw new \Exception('Wrong arguments');
            }
        }
        public function isDebugEnabled(): bool {
            return $this->debug;
        }
        public function setDebugEnabled(bool $enable = true): void {
            $this->debug = $enable;
        }
        public function getFilter(): ?Filter {
            if (count($this->filters) === 0) {
                return null;
            }
            return $this->filters[0];
        }
        public function setFilter(Filter $filter): void {
            $this->filters->clear();
            if ($filter !== null) {
                $this->filters->add($filter);
            }
        }
        public function addFilter(Filter $filter): void {
            $this->filters->add($filter);
        }
        public function removeFilter(Filter $filter): bool {
            $i = $this->filters->linearSearch($filter);
            if ($i === -1) {
                return false;
            }
            $this->filters->removeKey($i);
            return true;
        }
        public function getSimpleMode(): bool {
            return $this->simple;
        }
        public function setSimpleMode(bool $simple = true): void {
            $this->simple = $simple;
        }
        public function getErrorTypes(): int {
            return $this->error_types;
        }
        public function setErrorTypes(int $error_types): void {
            $this->error_types = $error_types;
        }
        public function defaultHandle(string $request,
                                      \stdClass $context): string {
            $input = new BytesIO($this->inputFilter($request, $context));
            try {
                switch ($input->getc()) {
                    case Tags::TagCall:
                        return $this->doInvoke($input, $context);
                    case Tags::TagEnd:
                        return $this->doFunctionList($context);
                    default:
                        throw new \Exception("Wrong Request: \r\n" . $request);
                }
            }
            catch (\Exception $e) {
                $error = $e->getMessage();
                if ($this->debug) {
                    $error .= "\nfile: " . $e->getFile() .
                              "\nline: " . $e->getLine() .
                              "\ntrace: " . $e->getTraceAsString();
                }
                return $this->sendError($error, $context);
            }
        }
    }
}
<commit_msg>Removed unnecessary ob_clean()<commit_after><?hh // strict
/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/

/**********************************************************\
 *                                                        *
 * Hprose/Service.hh                                      *
 *                                                        *
 * hprose service library for hack.                       *
 *                                                        *
 * LastModified: Mar 28, 2015                             *
 * Author: Ma Bingyao <andot@hprose.com>                  *
 *                                                        *
\**********************************************************/

namespace Hprose {
    class RemoteCall {
        public array<\ReflectionParameter> $params;
        public bool $byref;
        public function __construct(public mixed $func,
                                    public ResultMode $mode,
                                    public ?bool $simple) {
            if (is_array($func)) {
                $this->params = (new \ReflectionMethod($func[0], $func[1]))->getParameters();
            }
            else {
                $this->params = (new \ReflectionFunction($func))->getParameters();
            }
            $this->byref = false;
            foreach($this->params as $param) {
                if ($param->isPassedByReference()) {
                    $this->byref = true;
                    break;
                }
            }
        }
    }
    abstract class Service {
        private static array<string> $magic_methods = array(
            "__construct",
            "__destruct",
            "__call",
            "__callStatic",
            "__get",
            "__set",
            "__isset",
            "__unset",
            "__sleep",
            "__wakeup",
            "__toString",
            "__invoke",
            "__set_state",
            "__clone"
        );
        private Map<string, RemoteCall> $calls = Map {};
        private Vector<string> $names = Vector {};
        private Vector<Filter> $filters = Vector {};
        private bool $simple = false;
        protected bool $debug = false;
        protected int $error_types = E_ALL & ~E_NOTICE;
        public ?(function(string, array<mixed>, bool, \stdClass): void) $onBeforeInvoke = null;
        public ?(function(string, array<mixed>, bool, mixed, \stdClass): void) $onAfterInvoke = null;
        public ?(function(string, \stdClass): void) $onSendError = null;

        protected function inputFilter(string $data,
                                       \stdClass $context): string {
            $count = count($this->filters);
            for ($i = $count - 1; $i >= 0; $i--) {
                $data = $this->filters[$i]->inputFilter($data, $context);
            }
            return $data;
        }
        protected function outputFilter(string $data,
                                        \stdClass $context): string {
            $count = count($this->filters);
            for ($i = 0; $i < $count; $i++) {
                $data = $this->filters[$i]->outputFilter($data, $context);
            }
            return $data;
        }
        protected function sendError(string $error,
                                     \stdClass $context): string {
            if ($this->onSendError !== null) {
                $sendError = $this->onSendError;
                $sendError($error, $context);
            }
            $stream = new BytesIO();
            $writer = new Writer($stream, true);
            $stream->write(Tags::TagError);
            $writer->writeString($error);
            $stream->write(Tags::TagEnd);
            $data = $stream->toString();
            $stream->close();
            return $this->outputFilter($data, $context);
        }
        protected function doInvoke(BytesIO $input,
                                    \stdClass $context): string {
            $output = new BytesIO();
            $reader = new Reader($input);
            do {
                $reader->reset();
                $name = (string)$reader->readString();
                $alias = strtolower($name);
                if ($this->calls->contains($alias)) {
                    $call = $this->calls[$alias];
                }
                elseif ($this->calls->contains('*')) {
                    $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;
                $tag = $input->getc();
                if ($tag == Tags::TagList) {
                    $reader->reset();
                    $args = $reader->readListWithoutTag()->toArray();
                    $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;
                    $beforeInvoke($name, $args, $byref, $context);
                }
                if ($this->calls->contains('*') &&
                    $call === $this->calls['*']) {
                    $args = array($name, $args);
                }
                $result = call_user_func_array($call->func, $args);
                if ($this->onAfterInvoke !== null) {
                    $afterInvoke = $this->onAfterInvoke;
                    $afterInvoke($name, $args, $byref, $result, $context);
                }
                if ($mode == ResultMode::RawWithEndTag) {
                    return $this->outputFilter($result, $context);
                }
                elseif ($mode == ResultMode::Raw) {
                    $output->write($result);
                }
                else {
                    $writer = new Writer($output, $simple);
                    $output->write(Tags::TagResult);
                    if ($mode == ResultMode::Serialized) {
                        $output->write($result);
                    }
                    else {
                        $writer->reset();
                        $writer->serialize($result);
                    }
                    if ($byref) {
                        $output->write(Tags::TagArgument);
                        $writer->reset();
                        $writer->writeArray($args);
                    }
                }
            } while ($tag == Tags::TagCall);
            $output->write(Tags::TagEnd);
            return $this->outputFilter($output->toString(), $context);
        }
        protected function doFunctionList(\stdClass $context): string {
            $stream = new BytesIO();
            $writer = new Writer($stream, true);
            $stream->write(Tags::TagFunctions);
            $writer->writeList($this->names);
            $stream->write(Tags::TagEnd);
            $data = $stream->toString();
            $stream->close();
            return $this->outputFilter($data, $context);
        }
        private static function getDeclaredOnlyMethods(string $class): array<string> {
            $result = get_class_methods($class);
            if ($parent_class = get_parent_class($class)) {
                $inherit = get_class_methods($parent_class);
                $result = array_diff($result, $inherit);
            }
            $result = array_diff($result, self::$magic_methods);
            return $result;
        }
        public function addMissingFunction(mixed $func,
                                       ResultMode $mode = ResultMode::Normal,
                                       ?bool $simple = null): void {
            $this->addFunction($func, '*', $mode, $simple);
        }
        public function addFunction(mixed $func,
                                    string $alias = '',
                                    ResultMode $mode = ResultMode::Normal,
                                    ?bool $simple = null): void {
            if (!is_callable($func)) {
                throw new \Exception('Argument func is not callable.');
            }
            if ($alias == '') {
                if (is_string($func)) {
                    $alias = $func;
                }
                elseif (is_array($func)) {
                    $alias = $func[1];
                }
                else {
                    throw new \Exception('alias must be a string.');
                }
            }
            $name = strtolower($alias);
            if (!$this->calls->contains($name)) {
                $this->names->add($alias);
            }
            $this->calls[$name] = new RemoteCall($func, $mode, $simple);
        }
        public function addFunctions(array<mixed> $funcs,
                                     array<string> $aliases = array(),
                                     ResultMode $mode = ResultMode::Normal,
                                     ?bool $simple = null): void {
            $count = count($aliases);
            if ($count == 0) {
                foreach ($funcs as $func) {
                    $this->addFunction($func, '', $mode, $simple);
                }
            }
            elseif ($count == count($funcs)) {
                foreach ($funcs as $i => $func) {
                    $this->addFunction($func, $aliases[$i], $mode, $simple);
                }
            }
            else {
                throw new \Exception('The count of functions is not matched with aliases');
            }
        }
        public function addMethod(string $methodname,
                                  mixed $belongto,
                                  string $alias = '',
                                  ResultMode $mode = ResultMode::Normal,
                                  ?bool $simple = null): void {
            $func = array($belongto, $methodname);
            $this->addFunction($func, $alias, $mode, $simple);
        }
        public function addMethods(array<string> $methods,
                                   mixed $belongto,
                                   mixed $aliases = '',
                                   ResultMode $mode = ResultMode::Normal,
                                   ?bool $simple = null): void {
            if ($aliases === null || count($aliases) == 0) {
                $aliases = '';
            }
            $_aliases = array();
            if (is_string($aliases)) {
                $aliasPrefix = $aliases;
                if ($aliasPrefix !== '') {
                    $aliasPrefix .= '_';
                }
                foreach ($methods as $k => $method) {
                    $_aliases[$k] = $aliasPrefix . $method;
                }
            }
            elseif (is_array($aliases)) {
                $_aliases = $aliases;
            }
            elseif ($aliases instanceof \Indexish) {
                $_aliases = $aliases;
            }
            if (count($methods) != count($_aliases)) {
                throw new \Exception('The count of methods is not matched with aliases');
            }
            foreach($methods as $k => $method) {
                $func = array($belongto, $method);
                $this->addFunction($func, $_aliases[$k], $mode, $simple);
            }
        }
        public function addInstanceMethods(mixed $object,
                                        string $class = '',
                                        string $aliasPrefix = '',
                                        ResultMode $mode = ResultMode::Normal,
                                        ?bool $simple = null): void {
            if ($class == '') {
                $class = get_class($object);
            }
            $this->addMethods(self::getDeclaredOnlyMethods($class),
                              $object, $aliasPrefix, $mode, $simple);
        }
        public function addClassMethods(string $class,
                                        string $execclass = '',
                                        string $aliasPrefix = '',
                                        ResultMode $mode = ResultMode::Normal,
                                        ?bool $simple = null): void {
            if ($execclass == '') {
                $execclass = $class;
            }
            $this->addMethods(self::getDeclaredOnlyMethods($class),
                              $execclass, $aliasPrefix, $mode, $simple);
        }
        public function add(...): void {
            $args_num = func_num_args();
            $args = func_get_args();
            switch ($args_num) {
                case 1: {
                    if (is_callable($args[0])) {
                        $this->addFunction($args[0]);
                        return;
                    }
                    elseif (is_array($args[0])) {
                        $this->addFunctions($args[0]);
                        return;
                    }
                    elseif (is_object($args[0])) {
                        $this->addInstanceMethods($args[0]);
                        return;
                    }
                    elseif (is_string($args[0])) {
                        $this->addClassMethods($args[0]);
                        return;
                    }
                    break;
                }
                case 2: {
                    if (is_callable($args[0]) && is_string($args[1])) {
                        $this->addFunction($args[0], $args[1]);
                        return;
                    }
                    elseif (is_string($args[0])) {
                        if (is_string($args[1]) && !is_callable(array($args[1], $args[0]))) {
                            if (class_exists($args[1])) {
                                $this->addClassMethods($args[0], $args[1]);
                            }
                            else {
                                $this->addClassMethods($args[0], '', $args[1]);
                            }
                        }
                        else {
                            $this->addMethod($args[0], $args[1]);
                        }
                        return;
                    }
                    elseif (is_array($args[0])) {
                        if (is_array($args[1])) {
                            $this->addFunctions($args[0], $args[1]);
                        }
                        else {
                            $this->addMethods($args[0], $args[1]);
                        }
                        return;
                    }
                    elseif (is_object($args[0])) {
                        $this->addInstanceMethods($args[0], $args[1]);
                        return;
                    }
                    break;
                }
                case 3: {
                    if (is_callable($args[0]) && $args[1] == '' && is_string($args[2])) {
                        $this->addFunction($args[0], $args[2]);
                        return;
                    }
                    elseif (is_string($args[0]) && is_string($args[2])) {
                        if (is_string($args[1]) && !is_callable(array($args[0], $args[1]))) {
                            $this->addClassMethods($args[0], $args[1], $args[2]);
                        }
                        else {
                            $this->addMethod($args[0], $args[1], $args[2]);
                        }
                        return;
                    }
                    elseif (is_array($args[0])) {
                        if ($args[1] == '' && is_array($args[2])) {
                            $this->addFunctions($args[0], $args[2]);
                        }
                        else {
                            $this->addMethods($args[0], $args[1], $args[2]);
                        }
                        return;
                    }
                    elseif (is_object($args[0])) {
                        $this->addInstanceMethods($args[0], $args[1], $args[2]);
                        return;
                    }
                    break;
                }
                throw new \Exception('Wrong arguments');
            }
        }
        public function isDebugEnabled(): bool {
            return $this->debug;
        }
        public function setDebugEnabled(bool $enable = true): void {
            $this->debug = $enable;
        }
        public function getFilter(): ?Filter {
            if (count($this->filters) === 0) {
                return null;
            }
            return $this->filters[0];
        }
        public function setFilter(Filter $filter): void {
            $this->filters->clear();
            if ($filter !== null) {
                $this->filters->add($filter);
            }
        }
        public function addFilter(Filter $filter): void {
            $this->filters->add($filter);
        }
        public function removeFilter(Filter $filter): bool {
            $i = $this->filters->linearSearch($filter);
            if ($i === -1) {
                return false;
            }
            $this->filters->removeKey($i);
            return true;
        }
        public function getSimpleMode(): bool {
            return $this->simple;
        }
        public function setSimpleMode(bool $simple = true): void {
            $this->simple = $simple;
        }
        public function getErrorTypes(): int {
            return $this->error_types;
        }
        public function setErrorTypes(int $error_types): void {
            $this->error_types = $error_types;
        }
        public function defaultHandle(string $request,
                                      \stdClass $context): string {
            $input = new BytesIO($this->inputFilter($request, $context));
            try {
                switch ($input->getc()) {
                    case Tags::TagCall:
                        return $this->doInvoke($input, $context);
                    case Tags::TagEnd:
                        return $this->doFunctionList($context);
                    default:
                        throw new \Exception("Wrong Request: \r\n" . $request);
                }
            }
            catch (\Exception $e) {
                $error = $e->getMessage();
                if ($this->debug) {
                    $error .= "\nfile: " . $e->getFile() .
                              "\nline: " . $e->getLine() .
                              "\ntrace: " . $e->getTraceAsString();
                }
                return $this->sendError($error, $context);
            }
        }
    }
}
<|endoftext|>


<commit_before>// -*- mode: c++ , encoding: utf-8 -*-
/**
 * tbrpg – Text based roll playing game
 *
 * Copyright © 2012, 2013  Mattias Andrée (maandree@kth.se)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "BasicSenario.hpp"

/**
 * Text based roll playing game
 *
 * DD2387 Program construction with C++
 * Laboration 3
 *
 * @author  Mattias Andrée <maandree@kth.se>
 */
namespace tbrpg
{
  /**
   * Constructor
   */
  BasicSenario::BasicSenario() : Senario()
  {
    this->rules->party_size = 3;
    this->rules->party_start_size = 3;

    this->rules->inventory_prototype->personal[0] = new Gold();
    this->rules->inventory_prototype->personal[0]->quantity = 400;
    cleaner::getInstance().enqueueDelete(this->rules->inventory_prototype->personal[0]);

    MapMajor* map_town = new MapMajor();
    MapMajor* map_wilds = new MapMajor();

    MapMinor* area_inn = new House();
    MapMinor* area_town = new Town();
    MapMinor* area_wilds = new Wilderness();
    MapMinor* area_goal = new Wilderness();

    map_town->name = "The town";
    map_town->visible = true;
    map_town->visited = true;
    map_town->visitable = true;

    map_wilds->name = "Outside the town";
    map_wilds->visible = false;
    map_wilds->visited = false;
    map_wilds->visitable = true;
    map_wilds->detectable = true;

    area_inn->description = "You are standing in an inn.";
    area_inn->area = 40;
    (area_inn->is_in = map_town)->minors->push_back(area_inn);

    area_town->description = "You are standing in the marketplace.";
    area_town->area = 80;
    area_town->is_in = map_town;
    (area_town->is_in = map_town)->minors->push_back(area_town);

    area_wilds->description = "You are out on the open roads.";
    area_wilds->area = 80;
    area_wilds->is_in = map_wilds;
    (area_wilds->is_in = map_wilds)->minors->push_back(area_goal);

    area_goal->description = "You are in the wilderness.";
    area_goal->area = 80;
    area_goal->is_in = map_wilds;
    (area_goal->is_in = map_wilds)->minors->push_back(area_wilds);

    Road* road_out = new Road();
    Road* road_in = new Road();

    road_out->first_distance = road_in->last_distance = 1000;
    road_out->last_distance = road_in->first_distance = 1000;

    road_out->waylay_die = road_out->waylay_dice = 1;
    road_out->waylay_risk = 0;

    road_in->waylay_die = road_in->waylay_dice = 1;
    road_in->waylay_risk = 0;

    road_out->direction = "south";
    road_in->direction = "north";

    road_out->leads_to = area_wilds;
    road_in->leads_to = area_town;

    area_town->roads.push_back(road_out);
    area_wilds->roads.push_back(road_in);

    Door* door_in = new Door();
    Door* door_out = new Door();

    door_in->usable = true;
    door_out->usable = true;
    door_in->locked = false;
    door_out->locked = false;
    door_in->direction = "inn";
    door_out->direction = "town";
    door_in->description = "inn, you can rest safely here and get equipment";
    door_out->description = "the town";
    door_in->leads_to = area_inn;
    door_out->leads_to = area_town;

    area_town->connections.push_back(door_in);
    area_inn->connections.push_back(door_out);

    Entrance* next = new Entrance();
    Entrance* prev = new Entrance();

    next->usable = true;
    prev->usable = true;
    next->direction = "south";
    prev->direction = "north";
    next->description = "the wilderness";
    prev->description = "the open roads";
    next->leads_to = area_goal;
    prev->leads_to = area_wilds;
    area_goal->connections.push_back(prev);
    area_wilds->connections.push_back(next);

    Store* store = new Store();
    area_inn->creatures.push_back(store);

    this->map->start = area_town;
    this->map->majors->push_back(map_town);
    this->map->majors->push_back(map_wilds);

    store->room_costs.push_back(1);
    store->room_quality.push_back(2);
    store->room_costs.push_back(2);
    store->room_quality.push_back(4);
    store->room_costs.push_back(4);
    store->room_quality.push_back(8);
    store->room_costs.push_back(8);
    store->room_quality.push_back(16);

    store->record.race = &PROTOTYPE(Human);
    store->record.prestige.push_back(&PROTOTYPE(Fighter));

    store->inventory.push_back(&PROTOTYPE(ShortSword));
    store->inventory.push_back(&PROTOTYPE(LongSword));
    store->inventory.push_back(&PROTOTYPE(Bullet));
    store->inventory.push_back(&PROTOTYPE(Sling));
    store->inventory.push_back(&PROTOTYPE(ChainMail));
    store->inventory.push_back(&PROTOTYPE(Helmet));

    for (Item* item : store->inventory)
      item->quantity = -1;

    Key* questkey = new Key();
    questkey->id = 0;
    cleaner::getInstance().enqueueDelete(questkey);

    Creature* gibberling = new Creature();
    area_wilds->creatures.push_back(gibberling);
    gibberling->x = 50;
    gibberling->y = 50;
    gibberling->alive = true;
    gibberling->resurrect = false;
    gibberling->experience = 10;
    gibberling->record.name = "gibberling";
    gibberling->record.colour = 2;
    gibberling->record.alignment = 4;
    gibberling->record.inventory.personal.push_back(questkey);
    gibberling->record.race = &PROTOTYPE(Human);
    gibberling->record.prestige.push_back(&PROTOTYPE(Fighter));
  }

  /**
   * Copy constructor
   *
   * @param  original  The object to clone
   */
  BasicSenario::BasicSenario(const BasicSenario& original) : Senario(original)
  {
    (void) original;
  }

  /**
   * Copy constructor
   *
   * @param  original  The object to clone
   */
  BasicSenario::BasicSenario(BasicSenario& original) : Senario(original)
  {
    (void) original;
  }

  /**
   * Move constructor
   *
   * @param  original  The object to clone
   */
  BasicSenario::BasicSenario(BasicSenario&& original) : Senario(original)
  {
    (void) original;
  }

  /**
   * Fork the object
   *
   * @return  A fork of the object
   */
  Object* BasicSenario::fork() const
  {
    return (Object*)(new BasicSenario(*this));
  }

  /**
   * Destructor
   */
  BasicSenario::~BasicSenario()
  {
    // do nothing
  }

  /**
   * Assignment operator
   *
   * @param   original  The reference object
   * @return            The invoked object
   */
  BasicSenario& BasicSenario::operator =(const BasicSenario& original)
  {
    Object::__copy__((Senario&)*this, (Senario&)original);
    return *this;
  }

  /**
   * Assignment operator
   *
   * @param   original  The reference object
   * @return            The invoked object
   */
  BasicSenario& BasicSenario::operator =(BasicSenario& original)
  {
    Object::__copy__((Senario&)*this, (Senario&)original);
    return *this;
  }

  /**
   * Move operator
   *
   * @param   original  The moved object, its resourced will be moved
   * @return            The invoked object
   */
  BasicSenario& BasicSenario::operator =(BasicSenario&& original)
  {
    std::swap((Senario&)*this, (Senario&)original);
    return *this;
  }

  /**
   * This is invoked when the senario starts.
   * The prologue, and perhaps a short tutorial,
   * should be displayed.
   */
  void BasicSenario::start()
  {
    page("This is a simple demo senario.\n"
	 "\n"
	 "You stand outside an inn, where you purchase items such as"   "\n"
	 "armour and weapons that your need in your quest. You mission" "\n"
	 "is to the legendary sword known as Sword of Legends.");

    promptDialogue(2, "Tutor",
		   "examine map       :: Examine you world map"                             "\n"
		   "examine area      :: Examine the area"                                  "\n"
		   "examine party     :: Examine your character's abilities and spellbooks" "\n"
		   "examine inventory :: Open your inventorty, and pick up items"           "\n"
		   "turn undead [off] :: Turn on or off Turn Undead (special ability)"      "\n"
		   "find traps [off]  :: Turn on or off Find Traps (special ability)"       "\n"
		   "stealth [off]     :: Turn on or off Stealth Mode (special ability)"     "\n"
		   "pick pocket       :: Pick pocket a NPC (special ability)"               "\n"
		   "disarm            :: Disarm a found trap (special ability)"             "\n"
		   "unlock            :: Unlock a door or chest (special ability)"          "\n"
		   "bash              :: Bash a door or chest"                              "\n"
		   "specials          :: List other special ability commands you can use"   "\n"
		   "talk              :: Talk to a NPC"                                     "\n"
		   "travel            :: Go in some direction"                              "\n"
		   "cast ***          :: Cast a *** spell"                                  "\n"
		   "cast              :: Cast a non-quick spell"                            "\n"
		   "attack            :: Attack with you current weapon"                    "\n"
		   "weapon            :: Change your current weapon"                        "\n"
		   "quiver            :: Change the ammunition to use from you quiver"      "\n"
		   "rest              :: Rest, you party must be gathered"                  "\n"
		   "!                 :: Redo the last action that was not a wait action"   "\n"
		   ".                 :: Wait a turn"                                       "\n"
		   "quit              :: Stop playing", {});
  }

  /**
   * Gets the name of the game senario
   *
   * @return  The name of the game senario
   */
  std::string BasicSenario::getTitle()
  {
    return "Basic game senario demo";
  }

}

<commit_msg>m command intro<commit_after>// -*- mode: c++ , encoding: utf-8 -*-
/**
 * tbrpg – Text based roll playing game
 *
 * Copyright © 2012, 2013  Mattias Andrée (maandree@kth.se)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "BasicSenario.hpp"

/**
 * Text based roll playing game
 *
 * DD2387 Program construction with C++
 * Laboration 3
 *
 * @author  Mattias Andrée <maandree@kth.se>
 */
namespace tbrpg
{
  /**
   * Constructor
   */
  BasicSenario::BasicSenario() : Senario()
  {
    this->rules->party_size = 3;
    this->rules->party_start_size = 3;

    this->rules->inventory_prototype->personal[0] = new Gold();
    this->rules->inventory_prototype->personal[0]->quantity = 400;
    cleaner::getInstance().enqueueDelete(this->rules->inventory_prototype->personal[0]);

    MapMajor* map_town = new MapMajor();
    MapMajor* map_wilds = new MapMajor();

    MapMinor* area_inn = new House();
    MapMinor* area_town = new Town();
    MapMinor* area_wilds = new Wilderness();
    MapMinor* area_goal = new Wilderness();

    map_town->name = "The town";
    map_town->visible = true;
    map_town->visited = true;
    map_town->visitable = true;

    map_wilds->name = "Outside the town";
    map_wilds->visible = false;
    map_wilds->visited = false;
    map_wilds->visitable = true;
    map_wilds->detectable = true;

    area_inn->description = "You are standing in an inn.";
    area_inn->area = 40;
    (area_inn->is_in = map_town)->minors->push_back(area_inn);

    area_town->description = "You are standing in the marketplace.";
    area_town->area = 80;
    area_town->is_in = map_town;
    (area_town->is_in = map_town)->minors->push_back(area_town);

    area_wilds->description = "You are out on the open roads.";
    area_wilds->area = 80;
    area_wilds->is_in = map_wilds;
    (area_wilds->is_in = map_wilds)->minors->push_back(area_goal);

    area_goal->description = "You are in the wilderness.";
    area_goal->area = 80;
    area_goal->is_in = map_wilds;
    (area_goal->is_in = map_wilds)->minors->push_back(area_wilds);

    Road* road_out = new Road();
    Road* road_in = new Road();

    road_out->first_distance = road_in->last_distance = 1000;
    road_out->last_distance = road_in->first_distance = 1000;

    road_out->waylay_die = road_out->waylay_dice = 1;
    road_out->waylay_risk = 0;

    road_in->waylay_die = road_in->waylay_dice = 1;
    road_in->waylay_risk = 0;

    road_out->direction = "south";
    road_in->direction = "north";

    road_out->leads_to = area_wilds;
    road_in->leads_to = area_town;

    area_town->roads.push_back(road_out);
    area_wilds->roads.push_back(road_in);

    Door* door_in = new Door();
    Door* door_out = new Door();

    door_in->usable = true;
    door_out->usable = true;
    door_in->locked = false;
    door_out->locked = false;
    door_in->direction = "inn";
    door_out->direction = "town";
    door_in->description = "inn, you can rest safely here and get equipment";
    door_out->description = "the town";
    door_in->leads_to = area_inn;
    door_out->leads_to = area_town;

    area_town->connections.push_back(door_in);
    area_inn->connections.push_back(door_out);

    Entrance* next = new Entrance();
    Entrance* prev = new Entrance();

    next->usable = true;
    prev->usable = true;
    next->direction = "south";
    prev->direction = "north";
    next->description = "the wilderness";
    prev->description = "the open roads";
    next->leads_to = area_goal;
    prev->leads_to = area_wilds;
    area_goal->connections.push_back(prev);
    area_wilds->connections.push_back(next);

    Store* store = new Store();
    area_inn->creatures.push_back(store);

    this->map->start = area_town;
    this->map->majors->push_back(map_town);
    this->map->majors->push_back(map_wilds);

    store->room_costs.push_back(1);
    store->room_quality.push_back(2);
    store->room_costs.push_back(2);
    store->room_quality.push_back(4);
    store->room_costs.push_back(4);
    store->room_quality.push_back(8);
    store->room_costs.push_back(8);
    store->room_quality.push_back(16);

    store->record.race = &PROTOTYPE(Human);
    store->record.prestige.push_back(&PROTOTYPE(Fighter));

    store->inventory.push_back(&PROTOTYPE(ShortSword));
    store->inventory.push_back(&PROTOTYPE(LongSword));
    store->inventory.push_back(&PROTOTYPE(Bullet));
    store->inventory.push_back(&PROTOTYPE(Sling));
    store->inventory.push_back(&PROTOTYPE(ChainMail));
    store->inventory.push_back(&PROTOTYPE(Helmet));

    for (Item* item : store->inventory)
      item->quantity = -1;

    Key* questkey = new Key();
    questkey->id = 0;
    cleaner::getInstance().enqueueDelete(questkey);

    Creature* gibberling = new Creature();
    area_wilds->creatures.push_back(gibberling);
    gibberling->x = 50;
    gibberling->y = 50;
    gibberling->alive = true;
    gibberling->resurrect = false;
    gibberling->experience = 10;
    gibberling->record.name = "gibberling";
    gibberling->record.colour = 2;
    gibberling->record.alignment = 4;
    gibberling->record.inventory.personal.push_back(questkey);
    gibberling->record.race = &PROTOTYPE(Human);
    gibberling->record.prestige.push_back(&PROTOTYPE(Fighter));
  }

  /**
   * Copy constructor
   *
   * @param  original  The object to clone
   */
  BasicSenario::BasicSenario(const BasicSenario& original) : Senario(original)
  {
    (void) original;
  }

  /**
   * Copy constructor
   *
   * @param  original  The object to clone
   */
  BasicSenario::BasicSenario(BasicSenario& original) : Senario(original)
  {
    (void) original;
  }

  /**
   * Move constructor
   *
   * @param  original  The object to clone
   */
  BasicSenario::BasicSenario(BasicSenario&& original) : Senario(original)
  {
    (void) original;
  }

  /**
   * Fork the object
   *
   * @return  A fork of the object
   */
  Object* BasicSenario::fork() const
  {
    return (Object*)(new BasicSenario(*this));
  }

  /**
   * Destructor
   */
  BasicSenario::~BasicSenario()
  {
    // do nothing
  }

  /**
   * Assignment operator
   *
   * @param   original  The reference object
   * @return            The invoked object
   */
  BasicSenario& BasicSenario::operator =(const BasicSenario& original)
  {
    Object::__copy__((Senario&)*this, (Senario&)original);
    return *this;
  }

  /**
   * Assignment operator
   *
   * @param   original  The reference object
   * @return            The invoked object
   */
  BasicSenario& BasicSenario::operator =(BasicSenario& original)
  {
    Object::__copy__((Senario&)*this, (Senario&)original);
    return *this;
  }

  /**
   * Move operator
   *
   * @param   original  The moved object, its resourced will be moved
   * @return            The invoked object
   */
  BasicSenario& BasicSenario::operator =(BasicSenario&& original)
  {
    std::swap((Senario&)*this, (Senario&)original);
    return *this;
  }

  /**
   * This is invoked when the senario starts.
   * The prologue, and perhaps a short tutorial,
   * should be displayed.
   */
  void BasicSenario::start()
  {
    page("This is a simple demo senario.\n"
	 "\n"
	 "You stand outside an inn, where you purchase items such as"   "\n"
	 "armour and weapons that your need in your quest. You mission" "\n"
	 "is to the legendary sword known as Sword of Legends.");

    promptDialogue(2, "Tutor",
		   "examine map       :: Examine you world map"                             "\n"
		   "examine area      :: Examine the area"                                  "\n"
		   "examine party     :: Examine your character's abilities and spellbooks" "\n"
		   "examine inventory :: Open your inventorty, and pick up items"           "\n"
		   "turn undead [off] :: Turn on or off Turn Undead (special ability)"      "\n"
		   "find traps [off]  :: Turn on or off Find Traps (special ability)"       "\n"
		   "stealth [off]     :: Turn on or off Stealth Mode (special ability)"     "\n"
		   "bard song [off]   :: Turn on or off Bard Song (special ability)"        "\n"
		   "pick pocket       :: Pick pocket a NPC (special ability)"               "\n"
		   "disarm            :: Disarm a found trap (special ability)"             "\n"
		   "unlock            :: Unlock a door or chest (special ability)"          "\n"
		   "bash              :: Bash a door or chest"                              "\n"
		   "specials          :: List other special ability commands you can use"   "\n"
		   "talk              :: Talk to a NPC"                                     "\n"
		   "travel            :: Go in some direction"                              "\n"
		   "cast              :: Cast a spell"                                      "\n"
		   "attack            :: Attack with you current weapon"                    "\n"
		   "weapon            :: Change your current weapon"                        "\n"
		   "quiver            :: Change the ammunition to use from you quiver"      "\n"
		   "rest              :: Rest, you party must be gathered"                  "\n"
		   "!                 :: Redo the last action that was not a wait action"   "\n"
		   ".                 :: Wait a turn"                                       "\n"
		   "quit              :: Stop playing", {});
  }

  /**
   * Gets the name of the game senario
   *
   * @return  The name of the game senario
   */
  std::string BasicSenario::getTitle()
  {
    return "Basic game senario demo";
  }

}

<|endoftext|>


<commit_before>#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cstdint>
#include <cstdlib>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

using std::atof;
using std::count;
using std::cout;
using std::cerr;
using std::endl;
using std::getline;
using std::string;
using std::stringstream;
using std::ifstream;
using cv::filter2D;
using cv::imread;
using cv::Mat;
using cv::namedWindow;
using cv::Rect;
using cv::waitKey;

namespace {
/*
 \brief カーネルへオペレータをセット。

 \param row カーネルの行
 \param line ファイルから読み込まれた文字列
 \param size カーネルのサイズ
*/
void SetOperator(Mat row, const string& line, uint64_t size) {
  stringstream line_stream(line);
  for (uint64_t i = 0; i < size; ++i) {
    if (line_stream.good() && !line_stream.eof()) {
      string op;
      getline(line_stream, op, ',');
      // オペレータをセット
      row.at<double>(i) = static_cast<double>(atof(op.c_str()));
    } else { break; }
  }
};
/*!
 \brief ファイルを読み込み、カーネルを取得する。

 \param filename カーネルを表したCSVのファイル名
 \return カーネル。エラーが起きた場合は空の画像
*/
Mat GetKernel(const string& filename) {
  ifstream stream;
  stream.open(filename);

  if (stream.good()) {
    string line;
    getline(stream, line);

    // 最初の行からフィルタサイズを取得。
    uint64_t size = count(line.begin(), line.end(), ',') + 1;
    // カーネルの領域を確保
    Mat kernel = Mat::zeros(size, size, cv::DataType<double>::type);

    if (kernel.data == NULL) {
      return Mat();
    } else {
      SetOperator(kernel.row(0), line, size);

      for (uint64_t i = 1; i < size; ++i) {
        if (stream.good() && !stream.eof()) {
          getline(stream, line);
          SetOperator(kernel.row(i), line, size);
        } else { break; }
      }

      return kernel;
    }
  } else { return Mat(); }
}
/*!
 \brief 画像をカーネルに基づいた線形フィルタをかける。

 \param src 元画像
 \param kernel カーネル
 \return フィルタされた画像。元画像かカーネルにエラーがある場合、空の画像
*/
Mat Filter(const Mat& src, const Mat& kernel) {
  if (src.data != NULL && kernel.data != NULL) {
    Mat filtered;
    src.copyTo(filtered);

    filter2D(src, filtered, src.depth(), kernel, cv::Point(0, 0));
    return filtered;
  } else { return Mat(); }
}
/*!
 \brief エラーメッセージをウィンドウ名として表示。

 ウィンドウが閉じられた時、標準エラー出力にもエラーメッセージを出力する。

 \TODO もっといいエラーの表示方法はないものか...

 \param error_message エラーメッセージ
 \return 常ににEXIT_FAILURE
*/
int ShowErrorWindow(const std::string& error_message) {
  namedWindow(error_message, CV_WINDOW_AUTOSIZE);
  waitKey(0);

  cerr << error_message << endl;

  return EXIT_FAILURE;
}
/*!
 \brief 元画像をフィルタされた画像を表示。

 \param original 元画像
 \param filtered フィルタされた画像
 \return 常にEXIT_SUCCESS
*/
int ShowImageWindow(const Mat& original, const Mat& filtered) {
  Mat output = Mat::zeros(
      original.size().height,
      original.size().width * 2,
      original.type());

  // 元画像とフィルタされた画像を結合
  original.copyTo(Mat(output, Rect(0, 0, original.cols, original.rows)));
  filtered.copyTo(
      Mat(output, Rect(original.cols, 0, original.cols, original.rows)));

  string window_name("linear_filter");
  namedWindow(window_name, CV_WINDOW_AUTOSIZE);
  imshow(window_name, output);

  waitKey(0);

  return EXIT_SUCCESS;
}
/*!
 \brief ウィンドウを表示し、結果を出力。

 　'original'か'filtered'にエラーがある場合、エラーウィンドウを表示する。それ以
 外の場合はフィルタされた画像を表示する。

 \param original 元画像
 \param filtered フィルタされた画像
 \param エラーコード
 */
int ShowWindow(const cv::Mat& original, const cv::Mat& filtered) {
  if (original.data == NULL) {
    return ShowErrorWindow(string("failed to open the image."));
  } else if (filtered.data == NULL) {
    return ShowErrorWindow(string("failed to filter the image."));
  } else { return ShowImageWindow(original, filtered); }
}
/*!
 \brief 画像のファイル名を取得。

 プログラム引数が2つの時はデフォルトの値'input.jpg'を、それ以上の場合は第二引
 数をファイル名として返す。

 \param agrc argc
 \param argv argv
 \return 画像のファイル名
*/
std::string GetImageFilename(int argc, char** argv)
  { return (argc == 2)? string("input.jpg"): string(argv[1]); }
/*!
 \brief カーネルを記述したファイル名を取得。

 プログラム引数が2つの場合は第二引数を、それ以上の場合は第三引数をファイル名と
 して返す。

 \param argc argc
 \param argv argv
 \return カーネルを記述したファイル名
 */
std::string GetKernelFilename(int argc, char** argv)
  { return (argc == 2)? string(argv[1]): string(argv[2]); }
}  // namespace

int main(int argc, char** argv) {
  if (argc == 2 || argc == 3) {
    Mat original = imread(::GetImageFilename(argc, argv),
                          CV_LOAD_IMAGE_GRAYSCALE);

    exit(
        ::ShowWindow(
            original,
            ::Filter(original, ::GetKernel(::GetKernelFilename(argc, argv)))));
  } else {
    exit(
        ::ShowErrorWindow(
            string("Usage: linear_filter image_file filter_csv")));
  }

  return 0;
}

<commit_msg>::Rewind関数と::GetKernelSize関数を追加。<commit_after>#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cstdint>
#include <cstdlib>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

using std::atof;
using std::count;
using std::cout;
using std::cerr;
using std::endl;
using std::getline;
using std::ifstream;
using std::ios;
using std::string;
using std::stringstream;
using cv::filter2D;
using cv::imread;
using cv::Mat;
using cv::namedWindow;
using cv::Rect;
using cv::waitKey;

namespace {
/*!
 \brief ファイルストリームの走査位置を先頭へ戻す。

 \param stream ファイルストリーム
 \return ファイルストリーム
 */
ifstream& Rewind(ifstream& stream) {
  stream.clear();
  stream.seekg(0, ios::beg);
  return stream;
}
/*
 \brief カーネルへオペレータをセット。

 \param row カーネルの行
 \param line ファイルから読み込まれた文字列
 \param size カーネルのサイズ
*/
void SetOperator(Mat row, const string& line, uint64_t size) {
  stringstream line_stream(line);
  for (uint64_t i = 0; i < size; ++i) {
    if (line_stream.good() && !line_stream.eof()) {
      string op;
      getline(line_stream, op, ',');
      // オペレータをセット
      row.at<double>(i) = static_cast<double>(atof(op.c_str()));
    } else { break; }
  }
}
/*!
 \brief カーネルのサイズを取得。

 \param stream カーネルのファイルストリーム
 \return カーネルのサイズ
 */
int GetKernelSize(ifstream& stream) {
  string line;
  getline(stream, line);
  // 最初の行からフィルタサイズを取得。
  uint64_t size = count(line.begin(), line.end(), ',') + 1;

  return size;
}
/*!
 \brief ファイルを読み込み、カーネルを取得する。

 \param filename カーネルを表したCSVのファイル名
 \return カーネル。エラーが起きた場合は空の画像
*/
Mat GetKernel(const string& filename) {
  ifstream stream(filename);

  if (stream.good()) {
    int size = ::GetKernelSize(stream);
    // カーネルの領域を確保
    Mat kernel = Mat::zeros(size, size, cv::DataType<double>::type);

    if (kernel.data == NULL) {
      return Mat();
    } else {
      ::Rewind(stream);

      for (int i = 0; i < size; ++i) {
        string line;
        if (stream.good() && !stream.eof()) {
          getline(stream, line);
          SetOperator(kernel.row(i), line, size);
        } else { break; }
      }

      return kernel;
    }
  } else { return Mat(); }
}
/*!
 \brief 画像をカーネルに基づいた線形フィルタをかける。

 \param src 元画像
 \param kernel カーネル
 \return フィルタされた画像。元画像かカーネルにエラーがある場合、空の画像
*/
Mat Filter(const Mat& src, const Mat& kernel) {
  if (src.data != NULL && kernel.data != NULL) {
    Mat filtered;
    src.copyTo(filtered);

    filter2D(src, filtered, src.depth(), kernel, cv::Point(0, 0));
    return filtered;
  } else { return Mat(); }
}
/*!
 \brief エラーメッセージをウィンドウ名として表示。

 ウィンドウが閉じられた時、標準エラー出力にもエラーメッセージを出力する。

 \TODO もっといいエラーの表示方法はないものか...

 \param error_message エラーメッセージ
 \return 常ににEXIT_FAILURE
*/
int ShowErrorWindow(const std::string& error_message) {
  namedWindow(error_message, CV_WINDOW_AUTOSIZE);
  waitKey(0);

  cerr << error_message << endl;

  return EXIT_FAILURE;
}
/*!
 \brief 元画像をフィルタされた画像を表示。

 \param original 元画像
 \param filtered フィルタされた画像
 \return 常にEXIT_SUCCESS
*/
int ShowImageWindow(const Mat& original, const Mat& filtered) {
  Mat output = Mat::zeros(
      original.size().height,
      original.size().width * 2,
      original.type());

  // 元画像とフィルタされた画像を結合
  original.copyTo(Mat(output, Rect(0, 0, original.cols, original.rows)));
  filtered.copyTo(
      Mat(output, Rect(original.cols, 0, original.cols, original.rows)));

  string window_name("linear_filter");
  namedWindow(window_name, CV_WINDOW_AUTOSIZE);
  imshow(window_name, output);

  waitKey(0);

  return EXIT_SUCCESS;
}
/*!
 \brief ウィンドウを表示し、結果を出力。

 　'original'か'filtered'にエラーがある場合、エラーウィンドウを表示する。それ以
 外の場合はフィルタされた画像を表示する。

 \param original 元画像
 \param filtered フィルタされた画像
 \param エラーコード
 */
int ShowWindow(const cv::Mat& original, const cv::Mat& filtered) {
  if (original.data == NULL) {
    return ShowErrorWindow(string("failed to open the image."));
  } else if (filtered.data == NULL) {
    return ShowErrorWindow(string("failed to filter the image."));
  } else { return ShowImageWindow(original, filtered); }
}
/*!
 \brief 画像のファイル名を取得。

 プログラム引数が2つの時はデフォルトの値'input.jpg'を、それ以上の場合は第二引
 数をファイル名として返す。

 \param agrc argc
 \param argv argv
 \return 画像のファイル名
*/
std::string GetImageFilename(int argc, char** argv)
  { return (argc == 2)? string("input.jpg"): string(argv[1]); }
/*!
 \brief カーネルを記述したファイル名を取得。

 プログラム引数が2つの場合は第二引数を、それ以上の場合は第三引数をファイル名と
 して返す。

 \param argc argc
 \param argv argv
 \return カーネルを記述したファイル名
 */
std::string GetKernelFilename(int argc, char** argv)
  { return (argc == 2)? string(argv[1]): string(argv[2]); }
}  // namespace

int main(int argc, char** argv) {
  if (argc == 2 || argc == 3) {
    Mat original = imread(::GetImageFilename(argc, argv),
                          CV_LOAD_IMAGE_GRAYSCALE);

    exit(
        ::ShowWindow(
            original,
            ::Filter(original, ::GetKernel(::GetKernelFilename(argc, argv)))));
  } else {
    exit(
        ::ShowErrorWindow(
            string("Usage: linear_filter image_file filter_csv")));
  }

  return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2007-2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "V8InspectorFrontendHost.h"

#include "V8MouseEvent.h"
#include "bindings/v8/V8Binding.h"
#include "core/inspector/InspectorController.h"
#include "core/inspector/InspectorFrontendClient.h"
#include "core/inspector/InspectorFrontendHost.h"
#include "core/platform/HistogramSupport.h"
#include "wtf/text/WTFString.h"

namespace WebCore {

void V8InspectorFrontendHost::platformMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
#if OS(MACOSX)
    v8SetReturnValue(args, v8::String::NewSymbol("mac"));
#elif OS(LINUX)
    v8SetReturnValue(args, v8::String::NewSymbol("linux"));
#elif OS(FREEBSD)
    v8SetReturnValue(args, v8::String::NewSymbol("freebsd"));
#elif OS(OPENBSD)
    v8SetReturnValue(args, v8::String::NewSymbol("openbsd"));
#elif OS(WIN)
    v8SetReturnValue(args, v8::String::NewSymbol("windows"));
#else
    v8SetReturnValue(args, v8::String::NewSymbol("unknown"));
#endif
}

void V8InspectorFrontendHost::portMethodCustom(const v8::FunctionCallbackInfo<v8::Value>&)
{
}

static void populateContextMenuItems(v8::Local<v8::Array>& itemArray, ContextMenu& menu)
{
    for (size_t i = 0; i < itemArray->Length(); ++i) {
        v8::Local<v8::Object> item = v8::Local<v8::Object>::Cast(itemArray->Get(i));
        v8::Local<v8::Value> type = item->Get(v8::String::NewSymbol("type"));
        v8::Local<v8::Value> id = item->Get(v8::String::NewSymbol("id"));
        v8::Local<v8::Value> label = item->Get(v8::String::NewSymbol("label"));
        v8::Local<v8::Value> enabled = item->Get(v8::String::NewSymbol("enabled"));
        v8::Local<v8::Value> checked = item->Get(v8::String::NewSymbol("checked"));
        v8::Local<v8::Value> subItems = item->Get(v8::String::NewSymbol("subItems"));
        if (!type->IsString())
            continue;
        String typeString = toWebCoreStringWithNullCheck(type.As<v8::String>());
        if (typeString == "separator") {
            ContextMenuItem item(ContextMenuItem(SeparatorType,
                                 ContextMenuItemCustomTagNoAction,
                                 String()));
            menu.appendItem(item);
        } else if (typeString == "subMenu" && subItems->IsArray()) {
            ContextMenu subMenu;
            v8::Local<v8::Array> subItemsArray = v8::Local<v8::Array>::Cast(subItems);
            populateContextMenuItems(subItemsArray, subMenu);
            ContextMenuItem item(SubmenuType,
                                 ContextMenuItemCustomTagNoAction,
                                 toWebCoreStringWithNullCheck(label),
                                 &subMenu);
            menu.appendItem(item);
        } else {
            ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id->ToInt32()->Value());
            ContextMenuItem menuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, toWebCoreStringWithNullCheck(label));
            if (checked->IsBoolean())
                menuItem.setChecked(checked->ToBoolean()->Value());
            if (enabled->IsBoolean())
                menuItem.setEnabled(enabled->ToBoolean()->Value());
            menu.appendItem(menuItem);
        }
    }
}

void V8InspectorFrontendHost::showContextMenuMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    if (args.Length() < 2)
        return;

    v8::Local<v8::Object> eventWrapper = v8::Local<v8::Object>::Cast(args[0]);
    if (!V8MouseEvent::info.equals(toWrapperTypeInfo(eventWrapper)))
        return;

    Event* event = V8Event::toNative(eventWrapper);
    if (!args[1]->IsArray())
        return;

    v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(args[1]);
    ContextMenu menu;
    populateContextMenuItems(array, menu);

    InspectorFrontendHost* frontendHost = V8InspectorFrontendHost::toNative(args.Holder());
    Vector<ContextMenuItem> items = menu.items();
    frontendHost->showContextMenu(event, items);
}

static void histogramEnumeration(const char* name, const v8::FunctionCallbackInfo<v8::Value>& args, int boundaryValue)
{
    if (args.Length() < 1 || !args[0]->IsInt32())
        return;

    int sample = args[0]->ToInt32()->Value();
    if (sample < boundaryValue)
        HistogramSupport::histogramEnumeration(name, sample, boundaryValue);
}

void V8InspectorFrontendHost::recordActionTakenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    histogramEnumeration("DevTools.ActionTaken", args, 100);
}

void V8InspectorFrontendHost::recordPanelShownMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    histogramEnumeration("DevTools.PanelShown", args, 20);
}

void V8InspectorFrontendHost::recordSettingChangedMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    histogramEnumeration("DevTools.SettingChanged", args, 100);
}

} // namespace WebCore

<commit_msg>Use the platform=linux code path for other Unix-like platforms (FreeBSD and OpenBSD) as well, not just OS(LINUX) - with the exception of MacOS.<commit_after>/*
 * Copyright (C) 2007-2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "V8InspectorFrontendHost.h"

#include "V8MouseEvent.h"
#include "bindings/v8/V8Binding.h"
#include "core/inspector/InspectorController.h"
#include "core/inspector/InspectorFrontendClient.h"
#include "core/inspector/InspectorFrontendHost.h"
#include "core/platform/HistogramSupport.h"
#include "wtf/text/WTFString.h"

namespace WebCore {

void V8InspectorFrontendHost::platformMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
#if OS(MACOSX)
    v8SetReturnValue(args, v8::String::NewSymbol("mac"));
#elif OS(WIN)
    v8SetReturnValue(args, v8::String::NewSymbol("windows"));
#else // Unix-like systems
    v8SetReturnValue(args, v8::String::NewSymbol("linux"));
#endif
}

void V8InspectorFrontendHost::portMethodCustom(const v8::FunctionCallbackInfo<v8::Value>&)
{
}

static void populateContextMenuItems(v8::Local<v8::Array>& itemArray, ContextMenu& menu)
{
    for (size_t i = 0; i < itemArray->Length(); ++i) {
        v8::Local<v8::Object> item = v8::Local<v8::Object>::Cast(itemArray->Get(i));
        v8::Local<v8::Value> type = item->Get(v8::String::NewSymbol("type"));
        v8::Local<v8::Value> id = item->Get(v8::String::NewSymbol("id"));
        v8::Local<v8::Value> label = item->Get(v8::String::NewSymbol("label"));
        v8::Local<v8::Value> enabled = item->Get(v8::String::NewSymbol("enabled"));
        v8::Local<v8::Value> checked = item->Get(v8::String::NewSymbol("checked"));
        v8::Local<v8::Value> subItems = item->Get(v8::String::NewSymbol("subItems"));
        if (!type->IsString())
            continue;
        String typeString = toWebCoreStringWithNullCheck(type.As<v8::String>());
        if (typeString == "separator") {
            ContextMenuItem item(ContextMenuItem(SeparatorType,
                                 ContextMenuItemCustomTagNoAction,
                                 String()));
            menu.appendItem(item);
        } else if (typeString == "subMenu" && subItems->IsArray()) {
            ContextMenu subMenu;
            v8::Local<v8::Array> subItemsArray = v8::Local<v8::Array>::Cast(subItems);
            populateContextMenuItems(subItemsArray, subMenu);
            ContextMenuItem item(SubmenuType,
                                 ContextMenuItemCustomTagNoAction,
                                 toWebCoreStringWithNullCheck(label),
                                 &subMenu);
            menu.appendItem(item);
        } else {
            ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id->ToInt32()->Value());
            ContextMenuItem menuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, toWebCoreStringWithNullCheck(label));
            if (checked->IsBoolean())
                menuItem.setChecked(checked->ToBoolean()->Value());
            if (enabled->IsBoolean())
                menuItem.setEnabled(enabled->ToBoolean()->Value());
            menu.appendItem(menuItem);
        }
    }
}

void V8InspectorFrontendHost::showContextMenuMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    if (args.Length() < 2)
        return;

    v8::Local<v8::Object> eventWrapper = v8::Local<v8::Object>::Cast(args[0]);
    if (!V8MouseEvent::info.equals(toWrapperTypeInfo(eventWrapper)))
        return;

    Event* event = V8Event::toNative(eventWrapper);
    if (!args[1]->IsArray())
        return;

    v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(args[1]);
    ContextMenu menu;
    populateContextMenuItems(array, menu);

    InspectorFrontendHost* frontendHost = V8InspectorFrontendHost::toNative(args.Holder());
    Vector<ContextMenuItem> items = menu.items();
    frontendHost->showContextMenu(event, items);
}

static void histogramEnumeration(const char* name, const v8::FunctionCallbackInfo<v8::Value>& args, int boundaryValue)
{
    if (args.Length() < 1 || !args[0]->IsInt32())
        return;

    int sample = args[0]->ToInt32()->Value();
    if (sample < boundaryValue)
        HistogramSupport::histogramEnumeration(name, sample, boundaryValue);
}

void V8InspectorFrontendHost::recordActionTakenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    histogramEnumeration("DevTools.ActionTaken", args, 100);
}

void V8InspectorFrontendHost::recordPanelShownMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    histogramEnumeration("DevTools.PanelShown", args, 20);
}

void V8InspectorFrontendHost::recordSettingChangedMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    histogramEnumeration("DevTools.SettingChanged", args, 100);
}

} // namespace WebCore

<|endoftext|>


<commit_before>#include <GraphFilter.h>

#include <Graph.h>

#include <iostream>

using namespace std;

bool
GraphFilter::processTemporalData(Graph & target_graph, time_t start_time, time_t end_time, float start_sentiment, float end_sentiment, Graph & source_graph, RawStatistics & stats) {
  auto & sid = source_graph.getNodeArray().getTable()["source"];
  auto & soid = source_graph.getNodeArray().getTable()["id"];
  auto & user_type = source_graph.getNodeArray().getTable()["type"];
  auto & political_party = source_graph.getNodeArray().getTable()["party"];
  auto & name_column = source_graph.getNodeArray().getTable()["name"];
  auto & uname_column = source_graph.getNodeArray().getTable()["uname"];

  auto begin = source_graph.begin_edges();
  auto end = source_graph.end_edges();
  auto it = begin;

  if (current_pos == -1) {
    target_graph.clear();
    current_pos = 0;
    cerr << "restarting update, begin = " << begin.get() << ", cp = " << current_pos << ", end = " << end.get() << ", source = " << &source_graph << ", edges = " << source_graph.getEdgeCount() << endl;
  } else {
    cerr << "continuing update, begin = " << begin.get() << ", cp = " << current_pos << ", end = " << end.get() << ", source = " << &source_graph << ", edges = " << source_graph.getEdgeCount() << endl;
    for (int i = 0; i < current_pos; i++) {
      assert(it != end);
      ++it;
    }
  }

  auto & nodes = target_graph.getNodeArray();

  unsigned int skipped_count = 0;
  bool is_changed = false;
  unsigned int num_edges_processed = 0;
  for ( ; it != end; ++it, current_pos++) {
    num_edges_processed++;

    time_t t = 0;
    float se = 0;
    short lang = 0;
    long long app_id = -1, filter_id = -1;
    bool is_first = false;

    assert(it->face != -1);
    if (it->face != -1) {
      assert(it->face >= 0 && it->face < source_graph.getFaceCount());
      auto & fd = source_graph.getFaceAttributes(it->face);
      t = fd.timestamp;
      se = fd.sentiment;
      lang = fd.lang;
      app_id = fd.app_id;
      filter_id = fd.filter_id;
      is_first = fd.first_edge == current_pos;
    }

    if (it->tail < 0 || it->head < 0 || it->tail >= nodes.size() || it->head >= nodes.size()) {
      cerr << "invalid values: tail = " << it->tail << ", head = " << it->head << ", t = " << t << ", count = " << nodes.size() << ", n = " << num_edges_processed << endl;
      assert(0);
    }

    if ((!start_time || t >= start_time) && (!end_time || t < end_time) &&
	se >= start_sentiment && se <= end_sentiment) {
      if (t < min_time || min_time == 0) min_time = t;
      if (t > max_time) max_time = t;

      pair<int, int> np(it->tail, it->head);
      short first_user_sid = sid.getInt(np.first);
      short target_user_sid = sid.getInt(np.second);
      long long first_user_soid = soid.getInt64(np.first);
      long long target_user_soid = soid.getInt64(np.second);

      is_changed = true;

      auto & target_nd_old = nodes.getNodeData(np.second);
      NodeType target_type = target_nd_old.type;

      if (is_first) {
	stats.addActivity(t, first_user_sid, first_user_soid, lang, app_id, filter_id, PoliticalParty(political_party.getInt(np.first)));
      }

      if (!seen_nodes.count(np.second)) {
	seen_nodes.insert(np.second);
	UserType ut = UserType(user_type.getInt(np.second));
	if (ut != UNKNOWN_TYPE) stats.addUserType(ut);
	// stats.addPoliticalParty(PoliticalParty(political_party.getInt(np.first)));
	int type_node_id = -1;
	if (ut == MALE) type_node_id = nodes.createMaleNode();
	else if (ut == FEMALE) type_node_id = nodes.createFemaleNode();
	if (type_node_id != -1) {
	  target_graph.addEdge(np.first, type_node_id, -1, 0.125f);
	}
      }

      float weight = 1.0f;
      if (target_type == NODE_ANY) {
	stats.addReceivedActivity(t, target_user_sid, target_user_soid, app_id, filter_id);
      } else if (target_type == NODE_HASHTAG) {
	stats.addHashtag(name_column.getText(np.second));
	num_hashtags++;
	weight = 0.25f;
      } else if (target_type == NODE_URL) {
	stats.addLink(name_column.getText(np.second), uname_column.getText(np.second));
	num_links++;
	weight = 0.125f;
      }

      if ((keep_hashtags || target_type != NODE_HASHTAG) && (keep_links || target_type != NODE_URL)) {

	unordered_map<int, unordered_map<int, int> >::iterator it1;
	unordered_map<int, int>::iterator it2;
	if ((it1 = seen_edges.find(np.first)) != seen_edges.end() &&
	    (it2 = it1->second.find(np.second)) != it1->second.end()) {
#if 0
	  updateOutdegree(np.first, 1.0f);
	  updateIndegree(np.second, 1.0f);
	  updateNodeSize(np.first);
	  updateNodeSize(np.second);
#endif
	} else {
	  seen_edges[np.first][np.second] = target_graph.addEdge(np.first, np.second, -1, weight, 0);
	}
      }
    }
  }

  // cerr << "updated graph data, nodes = " << nodes.size() << ", edges = " << getEdgeCount() << ", min_sig = " << target_graph.getMinSignificance() << ", skipped = " << skipped_count << ", first = " << is_first_level << endl;

  stats.setTimeRange(min_time, max_time);
  stats.setNumRawNodes(nodes.size());
  stats.setNumRawEdges(source_graph.getEdgeCount());
  // stats.setNumPosts(num_posts);
  // stats.setNumActiveUsers(num_active_users);

  return is_changed;
}
<commit_msg>adjust weights<commit_after>#include <GraphFilter.h>

#include <Graph.h>

#include <iostream>

using namespace std;

bool
GraphFilter::processTemporalData(Graph & target_graph, time_t start_time, time_t end_time, float start_sentiment, float end_sentiment, Graph & source_graph, RawStatistics & stats) {
  auto & sid = source_graph.getNodeArray().getTable()["source"];
  auto & soid = source_graph.getNodeArray().getTable()["id"];
  auto & user_type = source_graph.getNodeArray().getTable()["type"];
  auto & political_party = source_graph.getNodeArray().getTable()["party"];
  auto & name_column = source_graph.getNodeArray().getTable()["name"];
  auto & uname_column = source_graph.getNodeArray().getTable()["uname"];

  auto begin = source_graph.begin_edges();
  auto end = source_graph.end_edges();
  auto it = begin;

  if (current_pos == -1) {
    target_graph.clear();
    current_pos = 0;
    cerr << "restarting update, begin = " << begin.get() << ", cp = " << current_pos << ", end = " << end.get() << ", source = " << &source_graph << ", edges = " << source_graph.getEdgeCount() << endl;
  } else {
    cerr << "continuing update, begin = " << begin.get() << ", cp = " << current_pos << ", end = " << end.get() << ", source = " << &source_graph << ", edges = " << source_graph.getEdgeCount() << endl;
    for (int i = 0; i < current_pos; i++) {
      assert(it != end);
      ++it;
    }
  }

  auto & nodes = target_graph.getNodeArray();

  unsigned int skipped_count = 0;
  bool is_changed = false;
  unsigned int num_edges_processed = 0;
  for ( ; it != end; ++it, current_pos++) {
    num_edges_processed++;

    time_t t = 0;
    float se = 0;
    short lang = 0;
    long long app_id = -1, filter_id = -1;
    bool is_first = false;

    assert(it->face != -1);
    if (it->face != -1) {
      assert(it->face >= 0 && it->face < source_graph.getFaceCount());
      auto & fd = source_graph.getFaceAttributes(it->face);
      t = fd.timestamp;
      se = fd.sentiment;
      lang = fd.lang;
      app_id = fd.app_id;
      filter_id = fd.filter_id;
      is_first = fd.first_edge == current_pos;
    }

    if (it->tail < 0 || it->head < 0 || it->tail >= nodes.size() || it->head >= nodes.size()) {
      cerr << "invalid values: tail = " << it->tail << ", head = " << it->head << ", t = " << t << ", count = " << nodes.size() << ", n = " << num_edges_processed << endl;
      assert(0);
    }

    if ((!start_time || t >= start_time) && (!end_time || t < end_time) &&
	se >= start_sentiment && se <= end_sentiment) {
      if (t < min_time || min_time == 0) min_time = t;
      if (t > max_time) max_time = t;

      pair<int, int> np(it->tail, it->head);
      short first_user_sid = sid.getInt(np.first);
      short target_user_sid = sid.getInt(np.second);
      long long first_user_soid = soid.getInt64(np.first);
      long long target_user_soid = soid.getInt64(np.second);

      is_changed = true;

      auto & target_nd_old = nodes.getNodeData(np.second);
      NodeType target_type = target_nd_old.type;

      if (is_first) {
	stats.addActivity(t, first_user_sid, first_user_soid, lang, app_id, filter_id, PoliticalParty(political_party.getInt(np.first)));
      }

      if (!seen_nodes.count(np.second)) {
	seen_nodes.insert(np.second);
	UserType ut = UserType(user_type.getInt(np.second));
	if (ut != UNKNOWN_TYPE) stats.addUserType(ut);
	// stats.addPoliticalParty(PoliticalParty(political_party.getInt(np.first)));
	int type_node_id = -1;
	if (ut == MALE) type_node_id = nodes.createMaleNode();
	else if (ut == FEMALE) type_node_id = nodes.createFemaleNode();
	if (type_node_id != -1) {
	  target_graph.addEdge(np.first, type_node_id, -1, 0.15f);
	}
      }

      float weight = 1.0f;
      if (target_type == NODE_ANY) {
	stats.addReceivedActivity(t, target_user_sid, target_user_soid, app_id, filter_id);
      } else if (target_type == NODE_HASHTAG) {
	stats.addHashtag(name_column.getText(np.second));
	num_hashtags++;
	weight = 0.25f;
      } else if (target_type == NODE_URL) {
	stats.addLink(name_column.getText(np.second), uname_column.getText(np.second));
	num_links++;
	weight = 0.15f;
      }

      if ((keep_hashtags || target_type != NODE_HASHTAG) && (keep_links || target_type != NODE_URL)) {

	unordered_map<int, unordered_map<int, int> >::iterator it1;
	unordered_map<int, int>::iterator it2;
	if ((it1 = seen_edges.find(np.first)) != seen_edges.end() &&
	    (it2 = it1->second.find(np.second)) != it1->second.end()) {
#if 0
	  updateOutdegree(np.first, 1.0f);
	  updateIndegree(np.second, 1.0f);
	  updateNodeSize(np.first);
	  updateNodeSize(np.second);
#endif
	} else {
	  seen_edges[np.first][np.second] = target_graph.addEdge(np.first, np.second, -1, weight, 0);
	}
      }
    }
  }

  // cerr << "updated graph data, nodes = " << nodes.size() << ", edges = " << getEdgeCount() << ", min_sig = " << target_graph.getMinSignificance() << ", skipped = " << skipped_count << ", first = " << is_first_level << endl;

  stats.setTimeRange(min_time, max_time);
  stats.setNumRawNodes(nodes.size());
  stats.setNumRawEdges(source_graph.getEdgeCount());
  // stats.setNumPosts(num_posts);
  // stats.setNumActiveUsers(num_active_users);

  return is_changed;
}
<|endoftext|>