<?php
/**
* Parse a .proto file and generates the classes in a file
* @author Nikolai Kordulla
*/
class PBParser
{
// the message types array of (field, param[]='repeated,required,optional')
var $m_types = array();
// the message classtype
var $c_types = array();
// different types
var $scalar_types = array('double', 'float', 'int32' => 'PBInt', 'int64' => 'PBInt',
'uint32', 'uint64', 'sint32' => 'PBSignedInt', 'sint64' => 'PBSignedInt',
'fixed32', 'fixed64', 'sfixed32', 'sfixed64',
'bool' => 'PBBool', 'string' => 'PBString', 'bytes' => 'PBString');
/**
* parses the profile and generates a filename with the name
* pb_proto_[NAME]
* @param String $protofile - the protofilename with the path
*/
public function parse($protofile)
{
$string = file_get_contents($protofile);
// now take the filename
//$filename = str_replace("\\", "/", $filename);
$filename = split("/", $protofile);
$filename = $filename[count($filename) - 1];
// strip the comments out of the protofile
$this->_strip_comments($string);
$string = trim($string);
$this->_parse_message_type($string, '');
unset($this->m_types[count($this->m_types)-1]);
//$this->m_types = $this->m_types[0]['value'];
// now create file with classes
$name = split('\.', $filename);
array_pop($name);
$name = join($name, '.');
$this->_create_class_file('pb_proto_' . $name . '.php');
}
/**
* Creates php class file for the proto file
*
* @param String $filename - the filename of the php file
*/
private function _create_class_file($filename)
{
$string = '';
foreach ($this->m_types as $classfile)
{
$classname = str_replace(".", "_", $classfile['name']);
if ($classfile['type'] == 'message')
{
$string .= 'class ' . $classname . " extends PBMessage\n{\n";
$this->_create_class_constructor($classfile['value'], $string, $classname);
$this->_create_class_body($classfile['value'], $string, $classname);
$this->c_types[$classfile['name']] = 'PBMessage';
}
else if ($classfile['type'] == 'enum')
{
$string .= 'class ' . $classname . " extends PBEnum\n{\n";
$this->_create_class_definition($classfile['value'], $string);
$this->c_types[$classfile['name']] = 'PBEnum';
}
// now create the class body with all set and get functions
$string .= "}\n";
}
file_put_contents($filename, '<?php' . "\n" . $string . '?>');
}
/**
* Gets the type
* @param field array
* @return type
*/
private function _get_type($field)
{
if (isset($this->scalar_types[$field['value']['type']]))
return $this->scalar_types[$field['value']['type']];
else if (isset($this->c_types[$field['value']['namespace']]))
return $this->c_types[$field['value']['namespace']];
return $this->c_types[$field['value']['type']];
}
/**
* Creates the class body with functions for each field
* @param Array $classfile
* @param String $string
* @param String $classname - classname
*/
private function _create_class_body($classfile, &$string, $classname)
{
foreach($classfile as $field)
{
$type = $this->_get_type($field);
//var_dump($type);
//$type = $this->_get_type($field['value']['type']);
if ( isset($field['value']['repeated']) && ( isset($this->scalar_types[$field['value']['type']])
|| $type == 'PBEnum') )
{
$string .= ' function ' . $field['value']['name'] . '($offset)' . "\n {\n";
$string .= ' $v = $this->_get_arr_value("' . $field['value']['value'] . '", $offset);' . "\n";
$string .= ' return $v->get_value();' . "\n";;
$string .= " }\n";
$string .= ' function append_' . $field['value']['name'] . '($value)' . "\n {\n";
$string .= ' $v = $this->_add_arr_value("' . $field['value']['value'] . '");' . "\n";
$string .= ' $v->set_value($value);' . "\n";;
$string .= " }\n";
$string .= ' function set_' . $field['value']['name'] . '($index, $value)' . "\n {\n";
$string .= ' $v = new $this->fields["' . $field['value']['value'] . '"]();' . "\n";
$string .= ' $v->set_value($value);' . "\n";
$string .= ' $this->_set_arr_value("' . $field['value']['value'] . '", $index, $v);' . "\n";
$string .= " }\n";
$string .= ' function remove_last_' . $field['value']['name'] . '()' . "\n {\n";
$string .= ' $this->_remove_last_arr_value("' . $field['value']['value'] . '");' . "\n";
$string .= " }\n";
$string .= ' function ' . $field['value']['name'] . '_size()' . "\n {\n";
$string .= ' return $this->_get_arr_size("' . $field['value']['value'] . '");' . "\n";
$string .= " }\n";
}
else if (isset($field['value']['repeated']))
{
$string .= ' function ' . $field['value']['name'] . '($offset)' . "\n {\n";
$string .= ' return $this->_get_arr_value("' . $field['value']['value'] . '", $offset);' . "\n";
$string .= " }\n";
$string .= ' function add_' . $field['value']['name'] . '()' . "\n {\n";
$string .= ' return $this->_add_arr_value("' . $field['value']['value'] . '");' . "\n";
$string .= " }\n";
$string .= ' function set_' . $field['value']['name'] . '($index, $value)' . "\n {\n";
$string .= ' $this->_set_arr_value("' . $field['value']['value'] . '", $index, $value);' . "\n";
$string .= " }\n";
$string .= ' function remove_last_' . $field['value']['name'] . '()' . "\n {\n";
$string .= ' $this->_remove_last_arr_value("' . $field['value']['value'] . '");' . "\n";
$string .= " }\n";
$string .= ' function ' . $field['value']['name'] . '_size()' . "\n {\n";
$string .= ' return $this->_get_arr_size("' . $field['value']['value'] . '");' . "\n";
$string .= " }\n";
}
else
{
$string .= ' function ' . $field['value']['name'] . "()\n {\n";
$string .= ' return $this->_get_value("' . $field['value']['value'] . '");' . "\n";
$string .= " }\n";
$string .= ' function set_' . $field['value']['name'] . '($value)' . "\n {\n";
$string .= ' return $this->_set_value("' . $field['value']['value'] . '", $value);' . "\n";
$string .= " }\n";
}
}
}
/**
* Creates the class definitions
* @param Array $classfile
* @param String $string
*/
private function _create_class_definition($classfile, &$string)
{
foreach($classfile as $field)
{
$string .= ' const ' . $field['0'] . ' = ' . $field['1'] . ";\n";
}
}
/**
* Creates the class constructor
* @param Array $classfile
* @param String $string
* @param String $classname - classname
*/
private function _create_class_constructor($classfile, &$string, $classname)
{
$string