/** * Parses protobuf file and returns MessageDescriptor * * @param FileDescriptor $file File descriptors * @param string $messageContent Protobuf message content * @param MessageDescriptor $parent Parent message (if nested) * * @return MessageDescriptor * * @throws Exception */ private function _parseMessageType(FileDescriptor $file, $messageContent, MessageDescriptor $parent = null, ServiceDescriptor $service = null) { if ($messageContent == '') { return; } while (strlen($messageContent) > 0) { $next = $this->_next($messageContent); if (strtolower($next) == 'message') { $messageContent = trim(substr($messageContent, strlen($next))); $name = $this->_next($messageContent); $offset = $this->_getBeginEnd($messageContent, '{', '}'); // now extract the content and call parse_message again $content = trim(substr($messageContent, $offset['begin'] + 1, $offset['end'] - $offset['begin'] - 2)); $childMessage = new MessageDescriptor($name, $file, $parent); $this->_parseMessageType($file, $content, $childMessage, $service); $messageContent = '' . trim(substr($messageContent, $offset['end'])); } else { if (strtolower($next) == 'service') { $messageContent = trim(substr($messageContent, strlen($next))); $name = $this->_next($messageContent); $offset = $this->_getBeginEnd($messageContent, '{', '}'); // now extract the content and call parse_message again $content = trim(substr($messageContent, $offset['begin'] + 1, $offset['end'] - $offset['begin'] - 2)); $rpcService = new ServiceDescriptor($name, $file, $service); $this->_parseMessageType($file, $content, $parent, $rpcService); $messageContent = '' . trim(substr($messageContent, $offset['end'])); } else { if (strtolower($next) == 'rpc') { $messageContent = trim(substr($messageContent, strlen($next))); $func_input = $this->_next($messageContent); $func_output = trim(substr($messageContent, strlen($func_input))); $offset_input = $this->_getBeginEnd($func_input, '(', ')'); $name = substr($func_input, 0, strpos($func_input, '(', 0)); $input_type = trim(substr($func_input, $offset_input['begin'] + 1, $offset_input['end'] - $offset_input['begin'] - 2)); $offset_output = $this->_getBeginEnd($func_output, '(', ')'); $output_type = trim(substr($func_output, $offset_output['begin'] + 1, $offset_output['end'] - $offset_output['begin'] - 2)); // now extract the content and call parse_message again $method = new MethodDescriptor($name, $input_type, $output_type, $file, $service); // removing it from string $messageContent = substr($messageContent, strpos($messageContent, ';') + 1, strlen($messageContent)); $messageContent = '' . trim($messageContent); } else { if (strtolower($next) == 'enum') { $messageContent = trim(substr($messageContent, strlen($next))); $name = $this->_next($messageContent); $offset = $this->_getBeginEnd($messageContent, '{', '}'); // now extract the content and call parse_message again $content = trim(substr($messageContent, $offset['begin'] + 1, $offset['end'] - $offset['begin'] - 2)); $enum = new EnumDescriptor($name, $file, $parent); $this->_parseEnum($enum, $content); // removing it from string $messageContent = '' . trim(substr($messageContent, $offset['end'])); } else { if (strtolower($next) == 'import') { $name = $this->_next($messageContent); $match = preg_match('/"([^"]+)";*\\s?/', $messageContent, $matches, PREG_OFFSET_CAPTURE); if (!$match) { throw new Exception('Malformed include / look at your import statement: ' . $messageContent); } $includedFilename = $matches[1][0]; if (!file_exists($includedFilename)) { throw new Exception('Included file ' . $includedFilename . ' does not exist'); } $messageContent = trim(substr($messageContent, $matches[0][1] + strlen($matches[0][0]))); $parserKey = realpath($includedFilename); if (!isset(self::$_parsers[$parserKey])) { $pbp = new ProtobufParser($this->_useNativeNamespaces); self::$_parsers[$parserKey] = $pbp; } $file->addDependency($pbp->parse($includedFilename)); } else { if (strtolower($next) == 'option') { // We don't support option parameters just yet, skip for now. $messageContent = preg_replace('/^.+\\n/', '', $messageContent); } else { if (strtolower($next) == 'package') { $match = preg_match('/package[\\s]+([^;]+);?/', $messageContent, $matches, PREG_OFFSET_CAPTURE); if (!$match) { throw new Exception('Malformed package'); } $file->setPackage($matches[1][0]); $messageContent = trim(substr($messageContent, $matches[0][1] + strlen($matches[0][0]))); } else { // now a normal field $match = preg_match('/(.*);/', $messageContent, $matches, PREG_OFFSET_CAPTURE); if (!$match || !$parent) { throw new Exception('Proto file missformed'); } $parent->addField($this->_parseField($matches[0][0])); $messageContent = trim(substr($messageContent, $matches[0][1] + strlen($matches[0][0]))); } } } } } } } } }
foreach ($matches as $key => $match) { unset($GLOBALS['argv'][$key]); unset($GLOBALS['argv'][$key + 1]); } } } if ($optionError || count($argv) != 2) { printf('USAGE: %s [OPTIONS] PROTO_FILE' . PHP_EOL, $argv[0]); printf(' -n, --use-namespaces Use native PHP namespaces' . PHP_EOL); printf(' -p, --filename-prefix [PREFIX] Specify a prefix for generated file names' . PHP_EOL); printf(' --psr Output class files in a psr-4 directory structure' . PHP_EOL); exit(1); } // Reindex argv $GLOBALS['argv'] = array_values($GLOBALS['argv']); $parser = new ProtobufParser($useNamespaces); if ($filenamePrefix !== false) { $parser->setFilenamePrefix($filenamePrefix); } if ($outputPsr !== false) { $parser->setSavePsrOutput(true); } $file = $argv[1]; if (!file_exists($file)) { printf($file . ' does not exist' . PHP_EOL); exit(1); } if (!is_file($file)) { printf($file . ' is not a file' . PHP_EOL); exit(1); }
/** * Parses protobuf file and returns MessageDescriptor * * @param FileDescriptor $file File descriptors * @param string $messageContent Protobuf message content * @param MessageDescriptor $parent Parent message (if nested) * * @return MessageDescriptor * * @throws Exception */ private function _parseMessageType(FileDescriptor $file, $messageContent, MessageDescriptor $parent = null) { // recursion sucks! $message = $parent; if ($messageContent == '') { return; } while (strlen($messageContent) > 0) { $next = $this->_next($messageContent); if (strtolower($next) == 'message') { $messageContent = trim(substr($messageContent, strlen($next))); $name = $this->_next($messageContent); $offset = $this->_getBeginEnd($messageContent, '{', '}'); // now extract the content and call parse_message again $content = trim(substr($messageContent, $offset['begin'] + 1, $offset['end'] - $offset['begin'] - 2)); $childMessage = new MessageDescriptor($name, $file, $parent); $this->_parseMessageType($file, $content, $childMessage); $messageContent = '' . trim(substr($messageContent, $offset['end'])); } else { if (strtolower($next) == 'enum') { $messageContent = trim(substr($messageContent, strlen($next))); $name = $this->_next($messageContent); $offset = $this->_getBeginEnd($messageContent, '{', '}'); // now extract the content and call parse_message again $content = trim(substr($messageContent, $offset['begin'] + 1, $offset['end'] - $offset['begin'] - 2)); $enum = new EnumDescriptor($name, $file, $message); $this->_parseEnum($enum, $content); // removing it from string $messageContent = '' . trim(substr($messageContent, $offset['end'])); } else { if (strtolower($next) == 'import') { $name = $this->_next($messageContent); $match = preg_match('/"([^"]+)";*\\s?/', $messageContent, $matches, PREG_OFFSET_CAPTURE); if (!$match) { throw new Exception('Malformed include / look at your import statement: ' . $messageContent); } $includedFilename = $matches[1][0]; if (!file_exists($includedFilename)) { throw new Exception('Included file ' . $includedFilename . ' does not exist'); } $messageContent = trim(substr($messageContent, $matches[0][1] + strlen($matches[0][0]))); $parserKey = realpath($includedFilename); if (!isset(self::$_parsers[$parserKey])) { $pbp = new ProtobufParser(); self::$_parsers[$parserKey] = $pbp; } $file->addDependency($pbp->parse($includedFilename)); } else { if (strtolower($next) == 'package') { $match = preg_match('/package[\\s]+([^;]+);?/', $messageContent, $matches, PREG_OFFSET_CAPTURE); if (!$match) { throw new Exception('Malformed package'); } $file->setPackage($matches[1][0]); $messageContent = trim(substr($messageContent, $matches[0][1] + strlen($matches[0][0]))); } else { // now a normal field $match = preg_match('/(.*);/', $messageContent, $matches, PREG_OFFSET_CAPTURE); if (!$match) { throw new Exception('Proto file missformed'); } $message->addField($this->_parseField($matches[0][0])); $messageContent = trim(substr($messageContent, $matches[0][1] + strlen($matches[0][0]))); } } } } } return $message; }
unset($GLOBALS['argv'][$key + 1]); } } } if ($optionError || count($argv) != 2) { printf('USAGE: %s [OPTIONS] PROTO_FILE' . PHP_EOL, $argv[0]); printf(' -n, --use-namespaces Use native PHP namespaces' . PHP_EOL); printf(' -p, --filename-prefix [PREFIX] Specify a prefix for generated file names' . PHP_EOL); printf(' -t [path] Target directory for output' . PHP_EOL); printf(' --psr Output class files in a psr-4 directory structure' . PHP_EOL); printf(' --compile-in-place Generated files will be outputted in the same directory as their source files' . PHP_EOL); exit(1); } // Reindex argv $GLOBALS['argv'] = array_values($GLOBALS['argv']); $parser = new ProtobufParser($useNamespaces, $shouldCompileInPlace); if ($filenamePrefix !== false) { $parser->setFilenamePrefix($filenamePrefix); } if ($outputPsr !== false) { $parser->setSavePsrOutput(true); } if ($targetDir !== false) { if (!is_dir($targetDir)) { printf('Target directory ' . $targetDir . ' does not exist' . PHP_EOL); exit(1); } $parser->setTargetDir($targetDir); } $file = $argv[1]; if (!file_exists($file)) {
<?php require 'ProtobufCompiler/ProtobufParser.php'; if (!debug_backtrace()) { if (!class_exists('\\ProtobufMessage')) { echo $argv[0] . ' requires protobuf extension installed to run' . PHP_EOL; exit(1); } if (count($argv) < 2 || count($argv) > 3) { printf('USAGE: %s PROTO_FILE [NAMESPACE]' . PHP_EOL, $argv[0]); exit(1); } $parser = new ProtobufParser(); $file = $argv[1]; if (isset($argv[2])) { $namespace = $argv[2]; } else { $namespace = null; } if (!file_exists($file)) { printf($file . ' does not exist' . PHP_EOL); exit(1); } if (!is_file($file)) { printf($file . ' is not a file' . PHP_EOL); exit(1); } try { $parser->parse($file, null, $namespace); } catch (Exception $e) { echo $e->getMessage() . PHP_EOL;
case '-n': case '--use-namespaces': $useNamespaces = true; break; default: $optionError = true; break; } array_splice($argv, $key, 1); } if ($optionError || count($argv) != 2) { printf('USAGE: %s [OPTIONS] PROTO_FILE' . PHP_EOL, $argv[0]); printf(' -n, --use-namespaces Use native PHP namespaces' . PHP_EOL); exit(1); } $parser = new ProtobufParser($useNamespaces); $file = $argv[1]; if (!file_exists($file)) { printf($file . ' does not exist' . PHP_EOL); exit(1); } if (!is_file($file)) { printf($file . ' is not a file' . PHP_EOL); exit(1); } try { $parser->parse($file); } catch (Exception $e) { echo $e->getMessage() . PHP_EOL; } }
/** * Parses protobuf file and returns MessageDescriptor * * @param FileDescriptor $file File descriptors * @param string $messageContent Protobuf message content * @param MessageDescriptor $parent Parent message (if nested) * * @return MessageDescriptor * * @throws Exception */ private function _parseMessageType(FileDescriptor $file, $messageContent, MessageDescriptor $parent = null) { if ($messageContent == '') { return; } while (strlen($messageContent) > 0) { $next = $this->_next($messageContent); if (strtolower($next) == 'message') { $messageContent = trim(substr($messageContent, strlen($next))); $name = $this->_next($messageContent); $offset = $this->_getBeginEnd($messageContent, '{', '}'); // now extract the content and call parse_message again $content = trim(substr($messageContent, $offset['begin'] + 1, $offset['end'] - $offset['begin'] - 2)); $childMessage = new MessageDescriptor($name, $file, $parent); $this->_parseMessageType($file, $content, $childMessage); $messageContent = '' . trim(substr($messageContent, $offset['end'])); } else { if (strtolower($next) == 'enum') { $messageContent = trim(substr($messageContent, strlen($next))); $name = $this->_next($messageContent); $offset = $this->_getBeginEnd($messageContent, '{', '}'); // now extract the content and call parse_message again $content = trim(substr($messageContent, $offset['begin'] + 1, $offset['end'] - $offset['begin'] - 2)); $enum = new EnumDescriptor($name, $file, $parent); $this->_parseEnum($enum, $content); // ignore ";" at the end of the enum definition if (strlen($messageContent) > $offset['end'] && $messageContent[$offset['end']] === ';') { $offset['end']++; } // removing it from string $messageContent = '' . trim(substr($messageContent, $offset['end'])); } else { if (strtolower($next) == 'import') { $name = $this->_next($messageContent); $match = preg_match('/"([^"]+)";*\\s?/', $messageContent, $matches, PREG_OFFSET_CAPTURE); if (!$match) { throw new Exception('Malformed include / look at your import statement: ' . $messageContent); } $includedFilename = $matches[1][0]; if (!file_exists($includedFilename)) { foreach ($this->_includes as &$dir) { $fn = $dir . "/" . $includedFilename; if (file_exists($fn)) { $includedFilename = $fn; break; } } } if (!file_exists($includedFilename)) { throw new Exception('Included file ' . $includedFilename . ' does not exist'); } $messageContent = trim(substr($messageContent, $matches[0][1] + strlen($matches[0][0]))); $parserKey = realpath($includedFilename); if (!isset(self::$_parsers[$parserKey])) { $pbp = new ProtobufParser($this->_useNativeNamespaces, $this->_includes); $pbp->setFilenamePrefix($this->_filenamePrefix); self::$_parsers[$parserKey] = $pbp; } else { $pbp = self::$_parsers[$parserKey]; } $file->addDependency($pbp->parse($includedFilename)); } else { if (strtolower($next) == 'option') { // We don't support option parameters just yet, skip for now. $messageContent = preg_replace('/^.+\\n/', '', $messageContent); } else { if (strtolower($next) == 'extensions') { // We don't support extension parameters just yet, skip for now. $messageContent = trim(preg_replace('/^.+;/', '', $messageContent)); } else { if (strtolower($next) == 'package') { $match = preg_match('/package[\\s]+([^;]+);?/', $messageContent, $matches, PREG_OFFSET_CAPTURE); if (!$match) { throw new Exception('Malformed package'); } $file->setPackage($matches[1][0]); $messageContent = trim(substr($messageContent, $matches[0][1] + strlen($matches[0][0]))); } else { // now a normal field $match = preg_match('/(.*);/', $messageContent, $matches, PREG_OFFSET_CAPTURE); if (!$match || !$parent) { throw new Exception('Proto file missformed'); } $parent->addField($this->_parseField($matches[0][0])); $messageContent = trim(substr($messageContent, $matches[0][1] + strlen($matches[0][0]))); } } } } } } } }