init
This commit is contained in:
692
librabbitmq/codegen.py
Normal file
692
librabbitmq/codegen.py
Normal file
@@ -0,0 +1,692 @@
|
||||
# Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors.
|
||||
# SPDX-License-Identifier: mit
|
||||
|
||||
|
||||
from amqp_codegen import *
|
||||
import string
|
||||
import re
|
||||
|
||||
|
||||
class Emitter(object):
|
||||
"""An object the trivially emits generated code lines.
|
||||
|
||||
This largely exists to be wrapped by more sophisticated emitter
|
||||
classes.
|
||||
"""
|
||||
|
||||
def __init__(self, prefix):
|
||||
self.prefix = prefix
|
||||
|
||||
def emit(self, line):
|
||||
"""Emit a line of generated code."""
|
||||
print(self.prefix + line)
|
||||
|
||||
|
||||
class BitDecoder(object):
|
||||
"""An emitter object that keeps track of the state involved in
|
||||
decoding the AMQP bit type."""
|
||||
|
||||
def __init__(self, emitter):
|
||||
self.emitter = emitter
|
||||
self.bit = 0
|
||||
|
||||
def emit(self, line):
|
||||
self.bit = 0
|
||||
self.emitter.emit(line)
|
||||
|
||||
def decode_bit(self, lvalue):
|
||||
"""Generate code to decode a value of the AMQP bit type into
|
||||
the given lvalue."""
|
||||
if self.bit == 0:
|
||||
self.emitter.emit("if (!amqp_decode_8(encoded, &offset, &bit_buffer)) return AMQP_STATUS_BAD_AMQP_DATA;")
|
||||
|
||||
self.emitter.emit("%s = (bit_buffer & (1 << %d)) ? 1 : 0;"
|
||||
% (lvalue, self.bit))
|
||||
self.bit += 1
|
||||
if self.bit == 8:
|
||||
self.bit = 0
|
||||
|
||||
|
||||
class BitEncoder(object):
|
||||
"""An emitter object that keeps track of the state involved in
|
||||
encoding the AMQP bit type."""
|
||||
|
||||
def __init__(self, emitter):
|
||||
self.emitter = emitter
|
||||
self.bit = 0
|
||||
|
||||
def flush(self):
|
||||
"""Flush the state associated with AMQP bit types."""
|
||||
if self.bit:
|
||||
self.emitter.emit("if (!amqp_encode_8(encoded, &offset, bit_buffer)) return AMQP_STATUS_BAD_AMQP_DATA;")
|
||||
self.bit = 0
|
||||
|
||||
def emit(self, line):
|
||||
self.flush()
|
||||
self.emitter.emit(line)
|
||||
|
||||
def encode_bit(self, value):
|
||||
"""Generate code to encode a value of the AMQP bit type from
|
||||
the given value."""
|
||||
if self.bit == 0:
|
||||
self.emitter.emit("bit_buffer = 0;")
|
||||
|
||||
self.emitter.emit("if (%s) bit_buffer |= (1 << %d);"
|
||||
% (value, self.bit))
|
||||
self.bit += 1
|
||||
if self.bit == 8:
|
||||
self.flush()
|
||||
|
||||
|
||||
class SimpleType(object):
|
||||
"""A AMQP type that corresponds to a simple scalar C value of a
|
||||
certain width."""
|
||||
|
||||
def __init__(self, bits):
|
||||
self.bits = bits
|
||||
self.ctype = "uint%d_t" % (bits,)
|
||||
|
||||
def decode(self, emitter, lvalue):
|
||||
emitter.emit("if (!amqp_decode_%d(encoded, &offset, &%s)) return AMQP_STATUS_BAD_AMQP_DATA;" % (self.bits, lvalue))
|
||||
|
||||
def encode(self, emitter, value):
|
||||
emitter.emit("if (!amqp_encode_%d(encoded, &offset, %s)) return AMQP_STATUS_BAD_AMQP_DATA;" % (self.bits, value))
|
||||
|
||||
def literal(self, value):
|
||||
return value
|
||||
|
||||
class StrType(object):
|
||||
"""The AMQP shortstr or longstr types."""
|
||||
|
||||
def __init__(self, lenbits):
|
||||
self.lenbits = lenbits
|
||||
self.ctype = "amqp_bytes_t"
|
||||
|
||||
def decode(self, emitter, lvalue):
|
||||
emitter.emit("{")
|
||||
emitter.emit(" uint%d_t len;" % (self.lenbits,))
|
||||
emitter.emit(" if (!amqp_decode_%d(encoded, &offset, &len)" % (self.lenbits,))
|
||||
emitter.emit(" || !amqp_decode_bytes(encoded, &offset, &%s, len))" % (lvalue,))
|
||||
emitter.emit(" return AMQP_STATUS_BAD_AMQP_DATA;")
|
||||
emitter.emit("}")
|
||||
|
||||
def encode(self, emitter, value):
|
||||
emitter.emit("if (UINT%d_MAX < %s.len" % (self.lenbits, value))
|
||||
emitter.emit(" || !amqp_encode_%d(encoded, &offset, (uint%d_t)%s.len)" %
|
||||
(self.lenbits, self.lenbits, value))
|
||||
emitter.emit(" || !amqp_encode_bytes(encoded, &offset, %s))" % (value,))
|
||||
emitter.emit(" return AMQP_STATUS_BAD_AMQP_DATA;")
|
||||
|
||||
def literal(self, value):
|
||||
if value != '':
|
||||
raise NotImplementedError()
|
||||
|
||||
return "amqp_empty_bytes"
|
||||
|
||||
class BitType(object):
|
||||
"""The AMQP bit type."""
|
||||
|
||||
def __init__(self):
|
||||
self.ctype = "amqp_boolean_t"
|
||||
|
||||
def decode(self, emitter, lvalue):
|
||||
emitter.decode_bit(lvalue)
|
||||
|
||||
def encode(self, emitter, value):
|
||||
emitter.encode_bit(value)
|
||||
|
||||
def literal(self, value):
|
||||
return {True: 1, False: 0}[value]
|
||||
|
||||
class TableType(object):
|
||||
"""The AMQP table type."""
|
||||
|
||||
def __init__(self):
|
||||
self.ctype = "amqp_table_t"
|
||||
|
||||
def decode(self, emitter, lvalue):
|
||||
emitter.emit("{")
|
||||
emitter.emit(" int res = amqp_decode_table(encoded, pool, &(%s), &offset);" % (lvalue,))
|
||||
emitter.emit(" if (res < 0) return res;")
|
||||
emitter.emit("}")
|
||||
|
||||
def encode(self, emitter, value):
|
||||
emitter.emit("{")
|
||||
emitter.emit(" int res = amqp_encode_table(encoded, &(%s), &offset);" % (value,))
|
||||
emitter.emit(" if (res < 0) return res;")
|
||||
emitter.emit("}")
|
||||
|
||||
def literal(self, value):
|
||||
raise NotImplementedError()
|
||||
|
||||
types = {
|
||||
'octet': SimpleType(8),
|
||||
'short': SimpleType(16),
|
||||
'long': SimpleType(32),
|
||||
'longlong': SimpleType(64),
|
||||
'shortstr': StrType(8),
|
||||
'longstr': StrType(32),
|
||||
'bit': BitType(),
|
||||
'table': TableType(),
|
||||
'timestamp': SimpleType(64),
|
||||
}
|
||||
|
||||
def typeFor(spec, f):
|
||||
"""Get a representation of the AMQP type of a field."""
|
||||
return types[spec.resolveDomain(f.domain)]
|
||||
|
||||
def c_ize(s):
|
||||
s = s.replace('-', '_')
|
||||
s = s.replace(' ', '_')
|
||||
return s
|
||||
|
||||
# When generating API functions corresponding to synchronous methods,
|
||||
# we need some information that isn't in the protocol def: Some
|
||||
# methods should not be exposed, indicated here by a False value.
|
||||
# Some methods should be exposed but certain fields should not be
|
||||
# exposed as parameters.
|
||||
apiMethodInfo = {
|
||||
"amqp_connection_start": False, # application code should not use this
|
||||
"amqp_connection_secure": False, # application code should not use this
|
||||
"amqp_connection_tune": False, # application code should not use this
|
||||
"amqp_connection_open": False, # application code should not use this
|
||||
"amqp_connection_close": False, # needs special handling
|
||||
"amqp_channel_open": ["out_of_band"],
|
||||
"amqp_channel_close": False, # needs special handling
|
||||
"amqp_access_request": False, # huh?
|
||||
"amqp_basic_get": False, # get-ok has content
|
||||
}
|
||||
|
||||
# When generating API functions corresponding to synchronous methods,
|
||||
# some fields should be suppressed everywhere. This dict names those
|
||||
# fields, and the fixed values to use for them.
|
||||
apiMethodsSuppressArgs = {"ticket": 0, "nowait": False}
|
||||
|
||||
AmqpMethod.defName = lambda m: cConstantName(c_ize(m.klass.name) + '_' + c_ize(m.name) + "_method")
|
||||
AmqpMethod.fullName = lambda m: "amqp_%s_%s" % (c_ize(m.klass.name), c_ize(m.name))
|
||||
AmqpMethod.structName = lambda m: m.fullName() + "_t"
|
||||
|
||||
AmqpClass.structName = lambda c: "amqp_" + c_ize(c.name) + "_properties_t"
|
||||
|
||||
def methodApiPrototype(m):
|
||||
fn = m.fullName()
|
||||
info = apiMethodInfo.get(fn, [])
|
||||
|
||||
docs = "/**\n * %s\n *\n" % (fn)
|
||||
docs += " * @param [in] state connection state\n"
|
||||
docs += " * @param [in] channel the channel to do the RPC on\n"
|
||||
|
||||
args = []
|
||||
for f in m.arguments:
|
||||
n = c_ize(f.name)
|
||||
if n in apiMethodsSuppressArgs or n in info:
|
||||
continue
|
||||
|
||||
args.append(", ")
|
||||
args.append(typeFor(m.klass.spec, f).ctype)
|
||||
args.append(" ")
|
||||
args.append(n)
|
||||
docs += " * @param [in] %s %s\n" % (n, n)
|
||||
|
||||
docs += " * @returns %s_ok_t\n" % (fn)
|
||||
docs += " */\n"
|
||||
|
||||
return "%sAMQP_EXPORT\n%s_ok_t *\nAMQP_CALL %s(amqp_connection_state_t state, amqp_channel_t channel%s)" % (docs, fn, fn, ''.join(args))
|
||||
|
||||
AmqpMethod.apiPrototype = methodApiPrototype
|
||||
|
||||
def cConstantName(s):
|
||||
return 'AMQP_' + '_'.join(re.split('[- ]', s.upper()))
|
||||
|
||||
def cFlagName(c, f):
|
||||
return cConstantName(c.name + '_' + f.name) + '_FLAG'
|
||||
|
||||
def genErl(spec):
|
||||
def fieldTempList(fields):
|
||||
return '[' + ', '.join(['F' + str(f.index) for f in fields]) + ']'
|
||||
|
||||
def fieldMapList(fields):
|
||||
return ', '.join([c_ize(f.name) + " = F" + str(f.index) for f in fields])
|
||||
|
||||
def genLookupMethodName(m):
|
||||
print(' case %s: return "%s";' % (m.defName(), m.defName()))
|
||||
|
||||
def genDecodeMethodFields(m):
|
||||
print(" case %s: {" % (m.defName(),))
|
||||
print(" %s *m = (%s *) amqp_pool_alloc(pool, sizeof(%s));" % \
|
||||
(m.structName(), m.structName(), m.structName()))
|
||||
print(" if (m == NULL) { return AMQP_STATUS_NO_MEMORY; }")
|
||||
|
||||
emitter = BitDecoder(Emitter(" "))
|
||||
for f in m.arguments:
|
||||
typeFor(spec, f).decode(emitter, "m->"+c_ize(f.name))
|
||||
|
||||
print(" *decoded = m;")
|
||||
print(" return 0;")
|
||||
print(" }")
|
||||
|
||||
def genDecodeProperties(c):
|
||||
print(" case %d: {" % (c.index,))
|
||||
print(" %s *p = (%s *) amqp_pool_alloc(pool, sizeof(%s));" % \
|
||||
(c.structName(), c.structName(), c.structName()))
|
||||
print(" if (p == NULL) { return AMQP_STATUS_NO_MEMORY; }")
|
||||
print(" p->_flags = flags;")
|
||||
|
||||
emitter = Emitter(" ")
|
||||
for f in c.fields:
|
||||
emitter.emit("if (flags & %s) {" % (cFlagName(c, f),))
|
||||
typeFor(spec, f).decode(emitter, "p->"+c_ize(f.name))
|
||||
emitter.emit("}")
|
||||
|
||||
print(" *decoded = p;")
|
||||
print(" return 0;")
|
||||
print(" }")
|
||||
|
||||
def genEncodeMethodFields(m):
|
||||
print(" case %s: {" % (m.defName(),))
|
||||
if m.arguments:
|
||||
print(" %s *m = (%s *) decoded;" % (m.structName(), m.structName()))
|
||||
|
||||
emitter = BitEncoder(Emitter(" "))
|
||||
for f in m.arguments:
|
||||
typeFor(spec, f).encode(emitter, "m->"+c_ize(f.name))
|
||||
emitter.flush()
|
||||
|
||||
print(" return (int)offset;")
|
||||
print(" }")
|
||||
|
||||
def genEncodeProperties(c):
|
||||
print(" case %d: {" % (c.index,))
|
||||
if c.fields:
|
||||
print(" %s *p = (%s *) decoded;" % (c.structName(), c.structName()))
|
||||
|
||||
emitter = Emitter(" ")
|
||||
for f in c.fields:
|
||||
emitter.emit(" if (flags & %s) {" % (cFlagName(c, f),))
|
||||
typeFor(spec, f).encode(emitter, "p->"+c_ize(f.name))
|
||||
emitter.emit("}")
|
||||
|
||||
print(" return (int)offset;")
|
||||
print(" }")
|
||||
|
||||
methods = spec.allMethods()
|
||||
|
||||
print("""// Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors.
|
||||
// SPDX-License-Identifier: mit
|
||||
|
||||
/* Generated code. Do not edit. Edit and re-run codegen.py instead. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "amqp_private.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
""")
|
||||
|
||||
print("""
|
||||
char const *amqp_constant_name(int constantNumber) {
|
||||
switch (constantNumber) {""")
|
||||
for (c,_,_) in spec.constants:
|
||||
print(" case %s: return \"%s\";" % (cConstantName(c), cConstantName(c)))
|
||||
print(""" default: return "(unknown)";
|
||||
}
|
||||
}""")
|
||||
|
||||
print("""
|
||||
amqp_boolean_t amqp_constant_is_hard_error(int constantNumber) {
|
||||
switch (constantNumber) {""")
|
||||
for (c,_,cls) in spec.constants:
|
||||
if cls == 'hard-error':
|
||||
print(" case %s: return 1;" % (cConstantName(c),))
|
||||
print(""" default: return 0;
|
||||
}
|
||||
}""")
|
||||
|
||||
print("""
|
||||
char const *amqp_method_name(amqp_method_number_t methodNumber) {
|
||||
switch (methodNumber) {""")
|
||||
for m in methods: genLookupMethodName(m)
|
||||
print(""" default: return NULL;
|
||||
}
|
||||
}""")
|
||||
|
||||
print("""
|
||||
amqp_boolean_t amqp_method_has_content(amqp_method_number_t methodNumber) {
|
||||
switch (methodNumber) {""")
|
||||
for m in methods:
|
||||
if m.hasContent:
|
||||
print(' case %s: return 1;' % (m.defName()))
|
||||
print(""" default: return 0;
|
||||
}
|
||||
}""")
|
||||
|
||||
print("""
|
||||
int amqp_decode_method(amqp_method_number_t methodNumber,
|
||||
amqp_pool_t *pool,
|
||||
amqp_bytes_t encoded,
|
||||
void **decoded)
|
||||
{
|
||||
size_t offset = 0;
|
||||
uint8_t bit_buffer;
|
||||
|
||||
switch (methodNumber) {""")
|
||||
for m in methods: genDecodeMethodFields(m)
|
||||
print(""" default: return AMQP_STATUS_UNKNOWN_METHOD;
|
||||
}
|
||||
}""")
|
||||
|
||||
print("""
|
||||
int amqp_decode_properties(uint16_t class_id,
|
||||
amqp_pool_t *pool,
|
||||
amqp_bytes_t encoded,
|
||||
void **decoded)
|
||||
{
|
||||
size_t offset = 0;
|
||||
|
||||
amqp_flags_t flags = 0;
|
||||
int flagword_index = 0;
|
||||
uint16_t partial_flags;
|
||||
|
||||
do {
|
||||
if (!amqp_decode_16(encoded, &offset, &partial_flags))
|
||||
return AMQP_STATUS_BAD_AMQP_DATA;
|
||||
flags |= (partial_flags << (flagword_index * 16));
|
||||
flagword_index++;
|
||||
} while (partial_flags & 1);
|
||||
|
||||
switch (class_id) {""")
|
||||
for c in spec.allClasses(): genDecodeProperties(c)
|
||||
print(""" default: return AMQP_STATUS_UNKNOWN_CLASS;
|
||||
}
|
||||
}""")
|
||||
|
||||
print("""
|
||||
int amqp_encode_method(amqp_method_number_t methodNumber,
|
||||
void *decoded,
|
||||
amqp_bytes_t encoded)
|
||||
{
|
||||
size_t offset = 0;
|
||||
uint8_t bit_buffer;
|
||||
|
||||
switch (methodNumber) {""")
|
||||
for m in methods: genEncodeMethodFields(m)
|
||||
print(""" default: return AMQP_STATUS_UNKNOWN_METHOD;
|
||||
}
|
||||
}""")
|
||||
|
||||
print("""
|
||||
int amqp_encode_properties(uint16_t class_id,
|
||||
void *decoded,
|
||||
amqp_bytes_t encoded)
|
||||
{
|
||||
size_t offset = 0;
|
||||
|
||||
/* Cheat, and get the flags out generically, relying on the
|
||||
similarity of structure between classes */
|
||||
amqp_flags_t flags = * (amqp_flags_t *) decoded; /* cheating! */
|
||||
|
||||
{
|
||||
/* We take a copy of flags to avoid destroying it, as it is used
|
||||
in the autogenerated code below. */
|
||||
amqp_flags_t remaining_flags = flags;
|
||||
do {
|
||||
amqp_flags_t remainder = remaining_flags >> 16;
|
||||
uint16_t partial_flags = remaining_flags & 0xFFFE;
|
||||
if (remainder != 0) { partial_flags |= 1; }
|
||||
if (!amqp_encode_16(encoded, &offset, partial_flags))
|
||||
return AMQP_STATUS_BAD_AMQP_DATA;
|
||||
remaining_flags = remainder;
|
||||
} while (remaining_flags != 0);
|
||||
}
|
||||
|
||||
switch (class_id) {""")
|
||||
for c in spec.allClasses(): genEncodeProperties(c)
|
||||
print(""" default: return AMQP_STATUS_UNKNOWN_CLASS;
|
||||
}
|
||||
}""")
|
||||
|
||||
for m in methods:
|
||||
if not m.isSynchronous:
|
||||
continue
|
||||
|
||||
info = apiMethodInfo.get(m.fullName(), [])
|
||||
if info is False:
|
||||
continue
|
||||
|
||||
print("")
|
||||
print(m.apiPrototype())
|
||||
print("{")
|
||||
print(" %s req;" % (m.structName(),))
|
||||
|
||||
for f in m.arguments:
|
||||
n = c_ize(f.name)
|
||||
|
||||
val = apiMethodsSuppressArgs.get(n)
|
||||
if val is None and n in info:
|
||||
val = f.defaultvalue
|
||||
|
||||
if val is None:
|
||||
val = n
|
||||
else:
|
||||
val = typeFor(spec, f).literal(val)
|
||||
|
||||
|
||||
print(" req.%s = %s;" % (n, val))
|
||||
|
||||
reply = cConstantName(c_ize(m.klass.name) + '_' + c_ize(m.name)
|
||||
+ "_ok_method")
|
||||
print("""
|
||||
return amqp_simple_rpc_decoded(state, channel, %s, %s, &req);
|
||||
}
|
||||
""" % (m.defName(), reply))
|
||||
|
||||
def genHrl(spec):
|
||||
def fieldDeclList(fields):
|
||||
if fields:
|
||||
return ''.join([" %s %s; /**< %s */\n" % (typeFor(spec, f).ctype,
|
||||
c_ize(f.name), f.name)
|
||||
for f in fields])
|
||||
else:
|
||||
return " char dummy; /**< Dummy field to avoid empty struct */\n"
|
||||
|
||||
def propDeclList(fields):
|
||||
return ''.join([" %s %s;\n" % (typeFor(spec, f).ctype, c_ize(f.name))
|
||||
for f in fields
|
||||
if spec.resolveDomain(f.domain) != 'bit'])
|
||||
|
||||
methods = spec.allMethods()
|
||||
|
||||
print("""// Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors.
|
||||
// SPDX-License-Identifier: mit
|
||||
|
||||
/* Generated code. Do not edit. Edit and re-run codegen.py instead. */
|
||||
|
||||
/** @file rabbitmq-c/framing.h */
|
||||
#ifndef RABBITMQ_C_FRAMING_H
|
||||
#define RABBITMQ_C_FRAMING_H
|
||||
|
||||
#include <rabbitmq-c/amqp.h>
|
||||
#include <rabbitmq-c/export.h>
|
||||
|
||||
AMQP_BEGIN_DECLS
|
||||
""")
|
||||
print("#define AMQP_PROTOCOL_VERSION_MAJOR %d /**< AMQP protocol version major */" % (spec.major))
|
||||
print("#define AMQP_PROTOCOL_VERSION_MINOR %d /**< AMQP protocol version minor */" % (spec.minor))
|
||||
print("#define AMQP_PROTOCOL_VERSION_REVISION %d /**< AMQP protocol version revision */" % (spec.revision))
|
||||
print("#define AMQP_PROTOCOL_PORT %d /**< Default AMQP Port */" % (spec.port))
|
||||
|
||||
for (c,v,cls) in spec.constants:
|
||||
print("#define %s %s /**< Constant: %s */" % (cConstantName(c), v, c))
|
||||
print("")
|
||||
|
||||
print("""/* Function prototypes. */
|
||||
|
||||
/**
|
||||
* Get constant name string from constant
|
||||
*
|
||||
* @param [in] constantNumber constant to get the name of
|
||||
* @returns string describing the constant. String is managed by
|
||||
* the library and should not be free()'d by the program
|
||||
*/
|
||||
AMQP_EXPORT
|
||||
char const *
|
||||
AMQP_CALL amqp_constant_name(int constantNumber);
|
||||
|
||||
/**
|
||||
* Checks to see if a constant is a hard error
|
||||
*
|
||||
* A hard error occurs when something severe enough
|
||||
* happens that the connection must be closed.
|
||||
*
|
||||
* @param [in] constantNumber the error constant
|
||||
* @returns true if its a hard error, false otherwise
|
||||
*/
|
||||
AMQP_EXPORT
|
||||
amqp_boolean_t
|
||||
AMQP_CALL amqp_constant_is_hard_error(int constantNumber);
|
||||
|
||||
/**
|
||||
* Get method name string from method number
|
||||
*
|
||||
* @param [in] methodNumber the method number
|
||||
* @returns method name string. String is managed by the library
|
||||
* and should not be freed()'d by the program
|
||||
*/
|
||||
AMQP_EXPORT
|
||||
char const *
|
||||
AMQP_CALL amqp_method_name(amqp_method_number_t methodNumber);
|
||||
|
||||
/**
|
||||
* Check whether a method has content
|
||||
*
|
||||
* A method that has content will receive the method frame
|
||||
* a properties frame, then 1 to N body frames
|
||||
*
|
||||
* @param [in] methodNumber the method number
|
||||
* @returns true if method has content, false otherwise
|
||||
*/
|
||||
AMQP_EXPORT
|
||||
amqp_boolean_t
|
||||
AMQP_CALL amqp_method_has_content(amqp_method_number_t methodNumber);
|
||||
|
||||
/**
|
||||
* Decodes a method from AMQP wireformat
|
||||
*
|
||||
* @param [in] methodNumber the method number for the decoded parameter
|
||||
* @param [in] pool the memory pool to allocate the decoded method from
|
||||
* @param [in] encoded the encoded byte string buffer
|
||||
* @param [out] decoded pointer to the decoded method struct
|
||||
* @returns 0 on success, an error code otherwise
|
||||
*/
|
||||
AMQP_EXPORT
|
||||
int
|
||||
AMQP_CALL amqp_decode_method(amqp_method_number_t methodNumber,
|
||||
amqp_pool_t *pool,
|
||||
amqp_bytes_t encoded,
|
||||
void **decoded);
|
||||
|
||||
/**
|
||||
* Decodes a header frame properties structure from AMQP wireformat
|
||||
*
|
||||
* @param [in] class_id the class id for the decoded parameter
|
||||
* @param [in] pool the memory pool to allocate the decoded properties from
|
||||
* @param [in] encoded the encoded byte string buffer
|
||||
* @param [out] decoded pointer to the decoded properties struct
|
||||
* @returns 0 on success, an error code otherwise
|
||||
*/
|
||||
AMQP_EXPORT
|
||||
int
|
||||
AMQP_CALL amqp_decode_properties(uint16_t class_id,
|
||||
amqp_pool_t *pool,
|
||||
amqp_bytes_t encoded,
|
||||
void **decoded);
|
||||
|
||||
/**
|
||||
* Encodes a method structure in AMQP wireformat
|
||||
*
|
||||
* @param [in] methodNumber the method number for the decoded parameter
|
||||
* @param [in] decoded the method structure (e.g., amqp_connection_start_t)
|
||||
* @param [in] encoded an allocated byte buffer for the encoded method
|
||||
* structure to be written to. If the buffer isn't large enough
|
||||
* to hold the encoded method, an error code will be returned.
|
||||
* @returns 0 on success, an error code otherwise.
|
||||
*/
|
||||
AMQP_EXPORT
|
||||
int
|
||||
AMQP_CALL amqp_encode_method(amqp_method_number_t methodNumber,
|
||||
void *decoded,
|
||||
amqp_bytes_t encoded);
|
||||
|
||||
/**
|
||||
* Encodes a properties structure in AMQP wireformat
|
||||
*
|
||||
* @param [in] class_id the class id for the decoded parameter
|
||||
* @param [in] decoded the properties structure (e.g., amqp_basic_properties_t)
|
||||
* @param [in] encoded an allocated byte buffer for the encoded properties to written to.
|
||||
* If the buffer isn't large enough to hold the encoded method, an
|
||||
* an error code will be returned
|
||||
* @returns 0 on success, an error code otherwise.
|
||||
*/
|
||||
AMQP_EXPORT
|
||||
int
|
||||
AMQP_CALL amqp_encode_properties(uint16_t class_id,
|
||||
void *decoded,
|
||||
amqp_bytes_t encoded);
|
||||
""")
|
||||
|
||||
print("/* Method field records. */\n")
|
||||
for m in methods:
|
||||
methodid = m.klass.index << 16 | m.index
|
||||
print("#define %s ((amqp_method_number_t) 0x%.08X) /**< %s.%s method id @internal %d, %d; %d */" % \
|
||||
(m.defName(),
|
||||
methodid,
|
||||
m.klass.name,
|
||||
m.name,
|
||||
m.klass.index,
|
||||
m.index,
|
||||
methodid))
|
||||
print("/** %s.%s method fields */\ntypedef struct %s_ {\n%s} %s;\n" % \
|
||||
(m.klass.name, m.name, m.structName(), fieldDeclList(m.arguments), m.structName()))
|
||||
|
||||
print("/* Class property records. */")
|
||||
for c in spec.allClasses():
|
||||
print("#define %s (0x%.04X) /**< %s class id @internal %d */" % \
|
||||
(cConstantName(c.name + "_class"), c.index, c.name, c.index))
|
||||
index = 0
|
||||
for f in c.fields:
|
||||
if index % 16 == 15:
|
||||
index = index + 1
|
||||
shortnum = index // 16
|
||||
partialindex = 15 - (index % 16)
|
||||
bitindex = shortnum * 16 + partialindex
|
||||
print('#define %s (1 << %d) /**< %s.%s property flag */' % (cFlagName(c, f), bitindex, c.name, f.name))
|
||||
index = index + 1
|
||||
print("/** %s class properties */\ntypedef struct %s_ {\n amqp_flags_t _flags; /**< bit-mask of set fields */\n%s} %s;\n" % \
|
||||
(c.name,
|
||||
c.structName(),
|
||||
fieldDeclList(c.fields),
|
||||
c.structName()))
|
||||
|
||||
print("/* API functions for methods */\n")
|
||||
|
||||
for m in methods:
|
||||
if m.isSynchronous and apiMethodInfo.get(m.fullName()) is not False:
|
||||
print("%s;" % (m.apiPrototype(),))
|
||||
|
||||
print("""
|
||||
AMQP_END_DECLS
|
||||
|
||||
#endif /* RABBITMQ_C_FRAMING_H */""")
|
||||
|
||||
def generateErl(specPath):
|
||||
genErl(AmqpSpec(specPath))
|
||||
|
||||
def generateHrl(specPath):
|
||||
genHrl(AmqpSpec(specPath))
|
||||
|
||||
if __name__ == "__main__":
|
||||
do_main(generateHrl, generateErl)
|
||||
Reference in New Issue
Block a user