778 lines
20 KiB
PHP
778 lines
20 KiB
PHP
<?php
|
|
|
|
function tokenize ($str, &$out) {
|
|
$out = array();
|
|
|
|
while (strlen($str) > 0) {
|
|
if (preg_match('/^\\/\\/.*/', $str, $matches)) {
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^\\s+/', $str, $matches)) {
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^include/', $str, $matches)) {
|
|
$out[] = array('include', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^message/', $str, $matches)) {
|
|
$out[] = array('message', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^repeated/', $str, $matches)) {
|
|
$out[] = array('repeated', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^required/', $str, $matches)) {
|
|
$out[] = array('required', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^optional/', $str, $matches)) {
|
|
$out[] = array('optional', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^{/', $str, $matches)) {
|
|
$out[] = array('spar', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^}/', $str, $matches)) {
|
|
$out[] = array('epar', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^\(/', $str, $matches)) {
|
|
$out[] = array('srpar', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^\)/', $str, $matches)) {
|
|
$out[] = array('erpar', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^=/', $str, $matches)) {
|
|
$out[] = array('equals', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^;/', $str, $matches)) {
|
|
$out[] = array('semicolon', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^uint(8|16|32|64)/', $str, $matches)) {
|
|
$out[] = array('uint', $matches[1]);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^data/', $str, $matches)) {
|
|
$out[] = array('data', null);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^[0-9]+/', $str, $matches)) {
|
|
$out[] = array('number', $matches[0]);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*/', $str, $matches)) {
|
|
$out[] = array('name', $matches[0]);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else if (preg_match('/^"([^"]*)"/', $str, $matches)) {
|
|
$out[] = array('string', $matches[1]);
|
|
$str = substr($str, strlen($matches[0]));
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
function fatal_error ($message)
|
|
{
|
|
fwrite(STDERR, "Fatal error: $message\n");
|
|
|
|
ob_get_clean();
|
|
exit(1);
|
|
}
|
|
|
|
function make_writer_decl ($msg, $entry)
|
|
{
|
|
switch ($entry["type"]["type"]) {
|
|
case "uint":
|
|
return "void {$msg["name"]}Writer_Add{$entry["name"]} ({$msg["name"]}Writer *o, uint{$entry["type"]["size"]}_t v)";
|
|
case "data":
|
|
return "uint8_t * {$msg["name"]}Writer_Add{$entry["name"]} ({$msg["name"]}Writer *o, int len)";
|
|
case "constdata":
|
|
return "uint8_t * {$msg["name"]}Writer_Add{$entry["name"]} ({$msg["name"]}Writer *o)";
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
function make_parser_decl ($msg, $entry)
|
|
{
|
|
switch ($entry["type"]["type"]) {
|
|
case "uint":
|
|
return "int {$msg["name"]}Parser_Get{$entry["name"]} ({$msg["name"]}Parser *o, uint{$entry["type"]["size"]}_t *v)";
|
|
case "data":
|
|
return "int {$msg["name"]}Parser_Get{$entry["name"]} ({$msg["name"]}Parser *o, uint8_t **data, int *data_len)";
|
|
case "constdata":
|
|
return "int {$msg["name"]}Parser_Get{$entry["name"]} ({$msg["name"]}Parser *o, uint8_t **data)";
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
function make_parser_reset_decl ($msg, $entry)
|
|
{
|
|
return "void {$msg["name"]}Parser_Reset{$entry["name"]} ({$msg["name"]}Parser *o)";
|
|
}
|
|
|
|
function make_parser_forward_decl ($msg, $entry)
|
|
{
|
|
return "void {$msg["name"]}Parser_Forward{$entry["name"]} ({$msg["name"]}Parser *o)";
|
|
}
|
|
|
|
function make_type_name ($msg, $entry)
|
|
{
|
|
switch ($entry["type"]["type"]) {
|
|
case "uint":
|
|
return "BPROTO_TYPE_UINT{$entry["type"]["size"]}";
|
|
case "data":
|
|
return "BPROTO_TYPE_DATA";
|
|
case "constdata":
|
|
return "BPROTO_TYPE_CONSTDATA";
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
function make_finish_assert ($msg, $entry)
|
|
{
|
|
switch ($entry["cardinality"]) {
|
|
case "repeated":
|
|
return "ASSERT(o->{$entry["name"]}_count >= 0)";
|
|
case "required repeated":
|
|
return "ASSERT(o->{$entry["name"]}_count >= 1)";
|
|
case "optional":
|
|
return "ASSERT(o->{$entry["name"]}_count >= 0 && o->{$entry["name"]}_count <= 1)";
|
|
case "required":
|
|
return "ASSERT(o->{$entry["name"]}_count == 1)";
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
function make_add_count_assert ($msg, $entry)
|
|
{
|
|
if (in_array($entry["cardinality"], array("optional", "required"))) {
|
|
return "ASSERT(o->{$entry["name"]}_count == 0)";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function make_add_length_assert ($msg, $entry)
|
|
{
|
|
if ($entry["type"]["type"] == "data") {
|
|
return "ASSERT(len >= 0 && len <= UINT32_MAX)";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function make_size_define ($msg, $entry)
|
|
{
|
|
switch ($entry["type"]["type"]) {
|
|
case "uint":
|
|
return "#define {$msg["name"]}_SIZE{$entry["name"]} (sizeof(struct BProto_header_s) + sizeof(struct BProto_uint{$entry["type"]["size"]}_s))";
|
|
case "data":
|
|
return "#define {$msg["name"]}_SIZE{$entry["name"]}(_len) (sizeof(struct BProto_header_s) + sizeof(struct BProto_data_header_s) + (_len))";
|
|
case "constdata":
|
|
return "#define {$msg["name"]}_SIZE{$entry["name"]} (sizeof(struct BProto_header_s) + sizeof(struct BProto_data_header_s) + ({$entry["type"]["size"]}))";
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
function generate_header ($name, $directives, $messages) {
|
|
ob_start();
|
|
|
|
echo <<<EOD
|
|
/*
|
|
DO NOT EDIT THIS FILE!
|
|
This file was automatically generated by the bproto generator.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include <misc/debug.h>
|
|
#include <misc/byteorder.h>
|
|
#include <bproto/BProto.h>
|
|
|
|
|
|
EOD;
|
|
|
|
foreach ($directives as $directive) {
|
|
if ($directive["type"] == "include") {
|
|
echo <<<EOD
|
|
#include "{$directive["file"]}"
|
|
|
|
EOD;
|
|
}
|
|
}
|
|
|
|
echo <<<EOD
|
|
|
|
|
|
EOD;
|
|
|
|
foreach ($messages as $msg) {
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
$def = make_size_define($msg, $entry);
|
|
echo <<<EOD
|
|
{$def}
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
|
|
typedef struct {
|
|
uint8_t *out;
|
|
int used;
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
echo <<<EOD
|
|
int {$entry["name"]}_count;
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
} {$msg["name"]}Writer;
|
|
|
|
static void {$msg["name"]}Writer_Init ({$msg["name"]}Writer *o, uint8_t *out);
|
|
static int {$msg["name"]}Writer_Finish ({$msg["name"]}Writer *o);
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
$decl = make_writer_decl($msg, $entry);
|
|
echo <<<EOD
|
|
static {$decl};
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
|
|
typedef struct {
|
|
uint8_t *buf;
|
|
int buf_len;
|
|
|
|
EOD;
|
|
foreach ($msg["entries"] as $entry) {
|
|
echo <<<EOD
|
|
int {$entry["name"]}_start;
|
|
int {$entry["name"]}_span;
|
|
int {$entry["name"]}_pos;
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
} {$msg["name"]}Parser;
|
|
|
|
static int {$msg["name"]}Parser_Init ({$msg["name"]}Parser *o, uint8_t *buf, int buf_len);
|
|
static int {$msg["name"]}Parser_GotEverything ({$msg["name"]}Parser *o);
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
$decl = make_parser_decl($msg, $entry);
|
|
$reset_decl = make_parser_reset_decl($msg, $entry);
|
|
$forward_decl = make_parser_forward_decl($msg, $entry);
|
|
echo <<<EOD
|
|
static {$decl};
|
|
static {$reset_decl};
|
|
static {$forward_decl};
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
|
|
void {$msg["name"]}Writer_Init ({$msg["name"]}Writer *o, uint8_t *out)
|
|
{
|
|
o->out = out;
|
|
o->used = 0;
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
echo <<<EOD
|
|
o->{$entry["name"]}_count = 0;
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
}
|
|
|
|
int {$msg["name"]}Writer_Finish ({$msg["name"]}Writer *o)
|
|
{
|
|
ASSERT(o->used >= 0)
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
$ass = make_finish_assert($msg, $entry);
|
|
echo <<<EOD
|
|
{$ass}
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
|
|
return o->used;
|
|
}
|
|
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
$decl = make_writer_decl($msg, $entry);
|
|
$type = make_type_name($msg, $entry);
|
|
$add_count_assert = make_add_count_assert($msg, $entry);
|
|
$add_length_assert = make_add_length_assert($msg, $entry);
|
|
|
|
echo <<<EOD
|
|
{$decl}
|
|
{
|
|
ASSERT(o->used >= 0)
|
|
{$add_count_assert}
|
|
{$add_length_assert}
|
|
|
|
struct BProto_header_s header;
|
|
header.id = htol16({$entry["id"]});
|
|
header.type = htol16({$type});
|
|
memcpy(o->out + o->used, &header, sizeof(header));
|
|
o->used += sizeof(struct BProto_header_s);
|
|
|
|
|
|
EOD;
|
|
switch ($entry["type"]["type"]) {
|
|
case "uint":
|
|
echo <<<EOD
|
|
struct BProto_uint{$entry["type"]["size"]}_s data;
|
|
data.v = htol{$entry["type"]["size"]}(v);
|
|
memcpy(o->out + o->used, &data, sizeof(data));
|
|
o->used += sizeof(struct BProto_uint{$entry["type"]["size"]}_s);
|
|
|
|
EOD;
|
|
break;
|
|
case "data":
|
|
echo <<<EOD
|
|
struct BProto_data_header_s data;
|
|
data.len = htol32(len);
|
|
memcpy(o->out + o->used, &data, sizeof(data));
|
|
o->used += sizeof(struct BProto_data_header_s);
|
|
|
|
uint8_t *dest = (o->out + o->used);
|
|
o->used += len;
|
|
|
|
EOD;
|
|
break;
|
|
case "constdata":
|
|
echo <<<EOD
|
|
struct BProto_data_header_s data;
|
|
data.len = htol32({$entry["type"]["size"]});
|
|
memcpy(o->out + o->used, &data, sizeof(data));
|
|
o->used += sizeof(struct BProto_data_header_s);
|
|
|
|
uint8_t *dest = (o->out + o->used);
|
|
o->used += ({$entry["type"]["size"]});
|
|
|
|
EOD;
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
echo <<<EOD
|
|
|
|
o->{$entry["name"]}_count++;
|
|
|
|
EOD;
|
|
if (in_array($entry["type"]["type"], array("data", "constdata"))) {
|
|
echo <<<EOD
|
|
|
|
return dest;
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
}
|
|
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
int {$msg["name"]}Parser_Init ({$msg["name"]}Parser *o, uint8_t *buf, int buf_len)
|
|
{
|
|
ASSERT(buf_len >= 0)
|
|
|
|
o->buf = buf;
|
|
o->buf_len = buf_len;
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
echo <<<EOD
|
|
o->{$entry["name"]}_start = o->buf_len;
|
|
o->{$entry["name"]}_span = 0;
|
|
o->{$entry["name"]}_pos = 0;
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
echo <<<EOD
|
|
int {$entry["name"]}_count = 0;
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
|
|
int pos = 0;
|
|
int left = o->buf_len;
|
|
|
|
while (left > 0) {
|
|
int entry_pos = pos;
|
|
|
|
if (!(left >= sizeof(struct BProto_header_s))) {
|
|
return 0;
|
|
}
|
|
struct BProto_header_s header;
|
|
memcpy(&header, o->buf + pos, sizeof(header));
|
|
pos += sizeof(struct BProto_header_s);
|
|
left -= sizeof(struct BProto_header_s);
|
|
uint16_t type = ltoh16(header.type);
|
|
uint16_t id = ltoh16(header.id);
|
|
|
|
switch (type) {
|
|
|
|
EOD;
|
|
|
|
foreach (array(8, 16, 32, 64) as $bits) {
|
|
echo <<<EOD
|
|
case BPROTO_TYPE_UINT{$bits}: {
|
|
if (!(left >= sizeof(struct BProto_uint{$bits}_s))) {
|
|
return 0;
|
|
}
|
|
pos += sizeof(struct BProto_uint{$bits}_s);
|
|
left -= sizeof(struct BProto_uint{$bits}_s);
|
|
|
|
switch (id) {
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
if (!($entry["type"]["type"] == "uint" && $entry["type"]["size"] == $bits)) {
|
|
continue;
|
|
}
|
|
$type = make_type_name($msg, $entry);
|
|
echo <<<EOD
|
|
case {$entry["id"]}:
|
|
if (o->{$entry["name"]}_start == o->buf_len) {
|
|
o->{$entry["name"]}_start = entry_pos;
|
|
}
|
|
o->{$entry["name"]}_span = pos - o->{$entry["name"]}_start;
|
|
{$entry["name"]}_count++;
|
|
break;
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
default:
|
|
return 0;
|
|
}
|
|
} break;
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
case BPROTO_TYPE_DATA:
|
|
case BPROTO_TYPE_CONSTDATA:
|
|
{
|
|
if (!(left >= sizeof(struct BProto_data_header_s))) {
|
|
return 0;
|
|
}
|
|
struct BProto_data_header_s val;
|
|
memcpy(&val, o->buf + pos, sizeof(val));
|
|
pos += sizeof(struct BProto_data_header_s);
|
|
left -= sizeof(struct BProto_data_header_s);
|
|
|
|
uint32_t payload_len = ltoh32(val.len);
|
|
if (!(left >= payload_len)) {
|
|
return 0;
|
|
}
|
|
pos += payload_len;
|
|
left -= payload_len;
|
|
|
|
switch (id) {
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
if (!in_array($entry["type"]["type"], array("data", "constdata"))) {
|
|
continue;
|
|
}
|
|
$type = make_type_name($msg, $entry);
|
|
echo <<<EOD
|
|
case {$entry["id"]}:
|
|
if (!(type == {$type})) {
|
|
return 0;
|
|
}
|
|
|
|
EOD;
|
|
if ($entry["type"]["type"] == "constdata") {
|
|
echo <<<EOD
|
|
if (!(payload_len == ({$entry["type"]["size"]}))) {
|
|
return 0;
|
|
}
|
|
|
|
EOD;
|
|
}
|
|
echo <<<EOD
|
|
if (o->{$entry["name"]}_start == o->buf_len) {
|
|
o->{$entry["name"]}_start = entry_pos;
|
|
}
|
|
o->{$entry["name"]}_span = pos - o->{$entry["name"]}_start;
|
|
{$entry["name"]}_count++;
|
|
break;
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
default:
|
|
return 0;
|
|
}
|
|
} break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
$cond = "";
|
|
switch ($entry["cardinality"]) {
|
|
case "repeated":
|
|
break;
|
|
case "required repeated":
|
|
$cond = "{$entry["name"]}_count >= 1";
|
|
break;
|
|
case "optional":
|
|
$cond = "{$entry["name"]}_count <= 1";
|
|
break;
|
|
case "required":
|
|
$cond = "{$entry["name"]}_count == 1";
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
if ($cond) {
|
|
echo <<<EOD
|
|
if (!({$cond})) {
|
|
return 0;
|
|
}
|
|
|
|
EOD;
|
|
}
|
|
}
|
|
|
|
echo <<<EOD
|
|
|
|
return 1;
|
|
}
|
|
|
|
int {$msg["name"]}Parser_GotEverything ({$msg["name"]}Parser *o)
|
|
{
|
|
return (
|
|
|
|
EOD;
|
|
|
|
$first = 1;
|
|
foreach ($msg["entries"] as $entry) {
|
|
if ($first) {
|
|
$first = 0;
|
|
} else {
|
|
echo <<<EOD
|
|
&&
|
|
|
|
EOD;
|
|
}
|
|
echo <<<EOD
|
|
o->{$entry["name"]}_pos == o->{$entry["name"]}_span
|
|
|
|
EOD;
|
|
}
|
|
|
|
|
|
echo <<<EOD
|
|
);
|
|
}
|
|
|
|
|
|
EOD;
|
|
|
|
foreach ($msg["entries"] as $entry) {
|
|
$decl = make_parser_decl($msg, $entry);
|
|
$reset_decl = make_parser_reset_decl($msg, $entry);
|
|
$forward_decl = make_parser_forward_decl($msg, $entry);
|
|
$type = make_type_name($msg, $entry);
|
|
|
|
echo <<<EOD
|
|
{$decl}
|
|
{
|
|
ASSERT(o->{$entry["name"]}_pos >= 0)
|
|
ASSERT(o->{$entry["name"]}_pos <= o->{$entry["name"]}_span)
|
|
|
|
int left = o->{$entry["name"]}_span - o->{$entry["name"]}_pos;
|
|
|
|
while (left > 0) {
|
|
ASSERT(left >= sizeof(struct BProto_header_s))
|
|
struct BProto_header_s header;
|
|
memcpy(&header, o->buf + o->{$entry["name"]}_start + o->{$entry["name"]}_pos, sizeof(header));
|
|
o->{$entry["name"]}_pos += sizeof(struct BProto_header_s);
|
|
left -= sizeof(struct BProto_header_s);
|
|
uint16_t type = ltoh16(header.type);
|
|
uint16_t id = ltoh16(header.id);
|
|
|
|
switch (type) {
|
|
|
|
EOD;
|
|
|
|
foreach (array(8, 16, 32, 64) as $bits) {
|
|
echo <<<EOD
|
|
case BPROTO_TYPE_UINT{$bits}: {
|
|
ASSERT(left >= sizeof(struct BProto_uint{$bits}_s))
|
|
|
|
EOD;
|
|
if ($entry["type"]["type"] == "uint" && $entry["type"]["size"] == $bits) {
|
|
echo <<<EOD
|
|
struct BProto_uint{$bits}_s val;
|
|
memcpy(&val, o->buf + o->{$entry["name"]}_start + o->{$entry["name"]}_pos, sizeof(val));
|
|
|
|
EOD;
|
|
}
|
|
echo <<<EOD
|
|
o->{$entry["name"]}_pos += sizeof(struct BProto_uint{$bits}_s);
|
|
left -= sizeof(struct BProto_uint{$bits}_s);
|
|
|
|
EOD;
|
|
if ($entry["type"]["type"] == "uint" && $entry["type"]["size"] == $bits) {
|
|
echo <<<EOD
|
|
|
|
if (id == {$entry["id"]}) {
|
|
*v = ltoh{$bits}(val.v);
|
|
return 1;
|
|
}
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
} break;
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
case BPROTO_TYPE_DATA:
|
|
case BPROTO_TYPE_CONSTDATA:
|
|
{
|
|
ASSERT(left >= sizeof(struct BProto_data_header_s))
|
|
struct BProto_data_header_s val;
|
|
memcpy(&val, o->buf + o->{$entry["name"]}_start + o->{$entry["name"]}_pos, sizeof(val));
|
|
o->{$entry["name"]}_pos += sizeof(struct BProto_data_header_s);
|
|
left -= sizeof(struct BProto_data_header_s);
|
|
|
|
uint32_t payload_len = ltoh32(val.len);
|
|
ASSERT(left >= payload_len)
|
|
|
|
EOD;
|
|
if ($entry["type"]["type"] == "data" || $entry["type"]["type"] == "constdata") {
|
|
echo <<<EOD
|
|
uint8_t *payload = o->buf + o->{$entry["name"]}_start + o->{$entry["name"]}_pos;
|
|
|
|
EOD;
|
|
}
|
|
echo <<<EOD
|
|
o->{$entry["name"]}_pos += payload_len;
|
|
left -= payload_len;
|
|
|
|
EOD;
|
|
if ($entry["type"]["type"] == "data") {
|
|
echo <<<EOD
|
|
|
|
if (type == BPROTO_TYPE_DATA && id == {$entry["id"]}) {
|
|
*data = payload;
|
|
*data_len = payload_len;
|
|
return 1;
|
|
}
|
|
|
|
EOD;
|
|
}
|
|
else if ($entry["type"]["type"] == "constdata") {
|
|
echo <<<EOD
|
|
|
|
if (type == BPROTO_TYPE_CONSTDATA && id == {$entry["id"]}) {
|
|
*data = payload;
|
|
return 1;
|
|
}
|
|
|
|
EOD;
|
|
}
|
|
|
|
echo <<<EOD
|
|
} break;
|
|
default:
|
|
ASSERT(0);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
{$reset_decl}
|
|
{
|
|
o->{$entry["name"]}_pos = 0;
|
|
}
|
|
|
|
{$forward_decl}
|
|
{
|
|
o->{$entry["name"]}_pos = o->{$entry["name"]}_span;
|
|
}
|
|
|
|
|
|
EOD;
|
|
}
|
|
}
|
|
|
|
return ob_get_clean();
|
|
}
|