asn1cによって生成されたxer_encode()関数は、コールバックを受け取ります。コールバックは、XERスニペットと、バイト単位のサイズ、およびuserdataポインターを取得します。適切なコールバックを作成することで、XERでエンコードされたデータをバッファーに入れることができます。
以下は私が私の問題を解決した方法です。バッファーを保持するxer_buffer_tを実装しました。そのサイズとバッファーの容量を追跡して、必要に応じてコールバックが再割り当てできるようにします。
void init_xer_buffer(xer_buffer_t* xer_buffer) {
xer_buffer->buffer = malloc(1024);
assert(xer_buffer->buffer != NULL);
xer_buffer->buffer_size = 1024;
xer_buffer->buffer_filled = 0;
}
void free_xer_buffer(xer_buffer_t* xer_buffer) {
free(xer_buffer->buffer);
xer_buffer->buffer_size = 0;
xer_buffer->buffer_filled = 0;
}
static int xer_print2xerbuf_cb(const void *buffer, size_t size, void *app_key) {
xer_buffer_t* xb = (xer_buffer_t*) app_key;
while (xb->buffer_size - xb->buffer_filled <= size+1) {
xb->buffer_size *= 2;
xb->buffer_size += 1;
xb->buffer = realloc(xb->buffer, xb->buffer_size);
assert(xb->buffer != NULL);
}
memcpy(xb->buffer+xb->buffer_filled, buffer, size);
xb->buffer_filled += size;
*(xb->buffer+xb->buffer_filled) = '\0';
return 1;
}
int xer_encode_to_buffer(xer_buffer_t* xb, asn_TYPE_descriptor_t *td, void *sptr) {
asn_enc_rval_t er;
if (!td || !sptr) return -1;
er = xer_encode(td, sptr, XER_F_BASIC, xer_print2xerbuf_cb, xb);
if (er.encoded == -1) return -1;
return 0;
}