From 01aa8b82dd0f8229355ffd2bb2bc8e8f496d2df6 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 26 Apr 2019 19:43:53 +0200 Subject: erl_interface: Tweak bit string encode/decode API to support zero copy decoding and bit offset arguments for future unaligned bit strings. --- lib/erl_interface/doc/src/ei.xml | 60 +++++++----- lib/erl_interface/include/ei.h | 8 +- lib/erl_interface/src/decode/decode_binary.c | 61 +++++++------ lib/erl_interface/src/decode/decode_skip.c | 10 +- lib/erl_interface/src/encode/encode_binary.c | 101 +++++++++++++++++++-- lib/erl_interface/src/misc/ei_printterm.c | 14 +-- lib/erl_interface/src/misc/ei_x_encode.c | 6 +- lib/erl_interface/src/misc/show_msg.c | 9 +- .../test/ei_connect_SUITE_data/ei_connect_test.c | 7 +- .../test/ei_decode_SUITE_data/ei_decode_test.c | 15 ++- lib/erl_interface/test/ei_decode_encode_SUITE.erl | 20 ++++ .../ei_decode_encode_test.c | 79 ++++++++++++++-- 12 files changed, 282 insertions(+), 108 deletions(-) (limited to 'lib') diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml index 254ae27cc8..7808bfd94f 100644 --- a/lib/erl_interface/doc/src/ei.xml +++ b/lib/erl_interface/doc/src/ei.xml @@ -183,28 +183,36 @@ typedef enum { - intei_decode_bitstring(const char *buf, int *index, void *p, size_t plen, size_t *bitsp) + intei_decode_bitstring(const char *buf, int *index, const char **pp, unsigned int *bitoffsp, size_t *nbitsp) Decode a bitstring. -

Decodes a bitstring from the binary format.

+

Decodes a bit string from the binary format.

- p -

Either NULL or points to a buffer where the bytes of the - bitstring will be written.

+ pp +

Either NULL or *pp returns a pointer to + the first byte of the bit string. The returned bit string is + readable as long as the buffer pointed to by buf is + readable and not written to.

- plen -

The max size of the bitstring in bytes, that is the - size of the buffer if p != NULL.

+ bitoffsp +

Either NULL or *bitoffsp returns the + number of unused bits in the first byte pointed to by + *pp. The value of *bitoffsp is between 0 and 7. + Unused bits in the first byte are the most significant bits.

- *bitsp -

If bitsp is not NULL, set to the actual - number of bits of the bitstring.

+ nbitsp +

Either NULL or *nbitsp returns the length + of the bit string in bits.

-

Returns 0 if it was a bitstring no longer than plen - bytes. The actual length of the bitstring will be - (*bitsp+7)/8 bytes. If (*bitsp % 8) > 0 only the high - (*bitsp % 8) bits of the last byte are significant.

+

Returns 0 if it was a bit string term.

+

The number of bytes pointed to by *pp, which are + part of the bit string, is (*bitoffsp + *nbitsp + 7)/8. If + (*bitoffsp + *bitsp)%8 > 0 then only (*bitoffsp + + *bitsp)%8 bits of the last byte are used. Unused bits in + the last byte are the least significant bits.

+

The values of unused bits in the first and last byte are undefined + and cannot be relied on.

Number of bits may be divisible by 8, which means a binary decodable by ei_decode_binary is also decodable by ei_decode_bitstring.

@@ -490,14 +498,24 @@ typedef enum {
- intei_encode_bitstring(char *buf, int *index, const void *p, size_t bits) - intei_x_encode_bitstring(ei_x_buff* x, const void *p, size_t bits) + int + ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t nbits) + int + ei_x_encode_bitstring(ei_x_buff* x, const char *p, size_t bitoffs, size_t nbits) Encode a bitstring. -

Encodes a bitstring in the binary format. The data is at - p. The size of the data is bits bits or - (bits+7)/8 bytes. If (bits%8) > 0 only the high - (bits%8) bits of the last byte are significant.

+

Encodes a bit string in the binary format.

+

The data is at p. The length of the bit string is nbits + bits. The first bitoffs bits of the data at p are unused. + The first byte which is part of the bit string is + p[bitoffs/8]. The bitoffs%8 most significant bits of + the first byte p[bitoffs/8] are unused.

+

The number of bytes which is part of the bit string is (bitoffs + + nbits + 7)/8. If (bitoffs + nbits)%8 > 0 then only (bitoffs + + nbits)%8 bits of the last byte are used. Unused bits in + the last byte are the least significant bits.

+

The values of unused bits are disregarded and does not need to be + cleared.

diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h index a860df3f77..ed0420300d 100644 --- a/lib/erl_interface/include/ei.h +++ b/lib/erl_interface/include/ei.h @@ -526,9 +526,9 @@ int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len); int ei_x_encode_atom_len_as(ei_x_buff* x, const char* s, int len, erlang_char_encoding from, erlang_char_encoding to); int ei_encode_binary(char *buf, int *index, const void *p, long len); -int ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits); +int ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t bits); int ei_x_encode_binary(ei_x_buff* x, const void* s, int len); -int ei_x_encode_bitstring(ei_x_buff* x, const void* p, size_t bits); +int ei_x_encode_bitstring(ei_x_buff* x, const char* p, size_t bitoffs, size_t bits); int ei_encode_pid(char *buf, int *index, const erlang_pid *p); int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid); int ei_encode_fun(char* buf, int* index, const erlang_fun* p); @@ -578,7 +578,9 @@ int ei_decode_string(const char *buf, int *index, char *p); int ei_decode_atom(const char *buf, int *index, char *p); int ei_decode_atom_as(const char *buf, int *index, char *p, int destlen, erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result); int ei_decode_binary(const char *buf, int *index, void *p, long *len); -int ei_decode_bitstring(const char *buf, int *index, void *p, size_t plen, size_t *bitsp); +int ei_decode_bitstring(const char *buf, int *index, const char** pp, + unsigned int* bitoffsp, size_t *nbitsp); + int ei_decode_fun(const char* buf, int* index, erlang_fun* p); void free_fun(erlang_fun* f); int ei_decode_pid(const char *buf, int *index, erlang_pid *p); diff --git a/lib/erl_interface/src/decode/decode_binary.c b/lib/erl_interface/src/decode/decode_binary.c index 2799438bef..0d28c67230 100644 --- a/lib/erl_interface/src/decode/decode_binary.c +++ b/lib/erl_interface/src/decode/decode_binary.c @@ -40,40 +40,41 @@ int ei_decode_binary(const char *buf, int *index, void *p, long *lenp) return 0; } -int ei_decode_bitstring(const char *buf, int *index, void *p, size_t plen, - size_t *bitsp) +int ei_decode_bitstring(const char *buf, int *index, + const char** pp, + unsigned int* bitoffsp, + size_t *nbitsp) { - const char *s = buf + *index; - const char *s0 = s; - unsigned long len; - unsigned char last_bits; - const unsigned char tag = get8(s); + const char *s = buf + *index; + const char *s0 = s; + unsigned char last_bits; + const unsigned char tag = get8(s); + size_t len = get32be(s); - if (tag == ERL_BINARY_EXT) { - long bytes; - int ret = ei_decode_binary(buf, index, p, &bytes); - if (bitsp) - *bitsp = (size_t)bytes * 8; - return ret; - } + switch(tag) { + case ERL_BINARY_EXT: + if (nbitsp) + *nbitsp = len * 8; + break; + case ERL_BIT_BINARY_EXT: + last_bits = get8(s); + if (((last_bits==0) != (len==0)) || last_bits > 8) + return -1; - if (tag != ERL_BIT_BINARY_EXT) - return -1; - - len = get32be(s); - last_bits = get8(s); - - if (len > plen || ((last_bits==0) != (len==0)) || last_bits > 8) - return -1; - - if (p) - memcpy(p, s, len); - s += len; + if (nbitsp) + *nbitsp = (len == 0) ? 0 : ((len-1) * 8) + last_bits; + break; + default: + return -1; + } - if (bitsp) - *bitsp = (len == 0) ? 0 : ((len-1) * 8) + last_bits; + if (pp) + *pp = s; + if (bitoffsp) + *bitoffsp = 0; - *index += s-s0; - return 0; + s += len; + *index += s-s0; + return 0; } diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c index 11d3bc1786..736c00e074 100644 --- a/lib/erl_interface/src/decode/decode_skip.c +++ b/lib/erl_interface/src/decode/decode_skip.c @@ -21,14 +21,6 @@ #include "eiext.h" #include "decode_skip.h" -#ifdef HAVE_STDINT_H -# include -#endif - -#ifndef SIZE_MAX -# define SIZE_MAX (~((size_t)0)) -#endif - int ei_skip_term(const char* buf, int* index) { int i, n, ty; @@ -88,7 +80,7 @@ int ei_skip_term(const char* buf, int* index) return -1; break; case ERL_BIT_BINARY_EXT: - if (ei_decode_bitstring(buf, index, NULL, SIZE_MAX, NULL) < 0) + if (ei_decode_bitstring(buf, index, NULL, NULL, NULL) < 0) return -1; break; case ERL_SMALL_INTEGER_EXT: diff --git a/lib/erl_interface/src/encode/encode_binary.c b/lib/erl_interface/src/encode/encode_binary.c index 4aa9f6bc16..0562979417 100644 --- a/lib/erl_interface/src/encode/encode_binary.c +++ b/lib/erl_interface/src/encode/encode_binary.c @@ -22,6 +22,10 @@ #include "eiext.h" #include "putget.h" +static void copy_bits(const unsigned char* src, size_t soffs, + unsigned char* dst, size_t n); + + int ei_encode_binary(char *buf, int *index, const void *p, long len) { char *s = buf + *index; @@ -40,23 +44,28 @@ int ei_encode_binary(char *buf, int *index, const void *p, long len) return 0; } -int ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits) +int ei_encode_bitstring(char *buf, int *index, + const char *p, + size_t bitoffs, + size_t bits) { char *s = buf + *index; char *s0 = s; size_t bytes = (bits + 7) / 8; char last_bits = bits % 8; - if (bytes == 0 || last_bits == 0) - return ei_encode_binary(buf, index, p, bytes); - - if (!buf) s += 6; + if (!buf) s += last_bits ? 6 : 5; else { - put8(s, ERL_BIT_BINARY_EXT); + char* tagp = s++; put32be(s, bytes); - put8(s, last_bits); - memcpy(s, p, bytes); - s[bytes-1] &= (0xff << (8-last_bits)); + if (last_bits) { + *tagp = ERL_BIT_BINARY_EXT; + put8(s, last_bits); + } + else + *tagp = ERL_BINARY_EXT; + + copy_bits((const unsigned char*)p, bitoffs, (unsigned char*)s, bits); } s += bytes; @@ -64,3 +73,77 @@ int ei_encode_bitstring(char *buf, int *index, const void *p, size_t bits) return 0; } + + +/* + * MAKE_MASK(n) constructs a mask with n bits. + * Example: MAKE_MASK(3) returns the binary number 00000111. + */ +#define MAKE_MASK(n) ((((unsigned) 1) << (n))-1) + + +static +void copy_bits(const unsigned char* src, /* Base pointer to source. */ + size_t soffs, /* Bit offset for source relative to src. */ + unsigned char* dst, /* Destination. */ + size_t n) /* Number of bits to copy. */ +{ + unsigned rmask; + unsigned count; + unsigned deoffs; + unsigned bits; + unsigned bits1; + unsigned rshift; + + if (n == 0) + return; + + deoffs = n & 7; + rmask = deoffs ? (MAKE_MASK(deoffs) << (8-deoffs)) : 0; + + if (soffs == 0) { + unsigned nbytes = (n + 7) / 8; + memcpy(dst, src, nbytes); + if (rmask) + dst[nbytes-1] &= rmask; + return; + } + + src += soffs / 8; + soffs &= 7; + + if (n < 8) { /* Less than one byte */ + bits = (*src << soffs); + if (soffs+n > 8) { + src++; + bits |= (*src >> (8 - soffs)); + } + *dst = bits & rmask; + return; + } + + count = n >> 3; + + rshift = 8 - soffs; + bits = *src; + if (soffs + n > 8) { + src++; + } + + while (count--) { + bits1 = bits << soffs; + bits = *src; + src++; + *dst = bits1 | (bits >> rshift); + dst++; + } + + if (rmask) { + bits1 = bits << soffs; + if ((rmask << rshift) & 0xff) { + bits = *src; + bits1 |= (bits >> rshift); + } + *dst = bits1 & rmask; + } +} diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c index a89b990ac1..5c40fb7747 100644 --- a/lib/erl_interface/src/misc/ei_printterm.c +++ b/lib/erl_interface/src/misc/ei_printterm.c @@ -250,12 +250,13 @@ static int print_term(FILE* fp, ei_x_buff* x, ei_free(p); break; case ERL_BIT_BINARY_EXT: { + const char* cp; size_t bits; + unsigned int bitoffs; int trunc = 0; - p = ei_malloc(n); - if (p == NULL) goto err; - if (ei_decode_bitstring(buf, index, p, n, &bits) < 0) { - ei_free(p); + + if (ei_decode_bitstring(buf, index, &cp, &bitoffs, &bits) < 0 + || bitoffs != 0) { goto err; } ch_written += xprintf(fp, x, "#Bits<"); @@ -266,15 +267,14 @@ static int print_term(FILE* fp, ei_x_buff* x, } --m; for (i = 0; i < m; ++i) { - ch_written += xprintf(fp, x, "%d,", p[i]); + ch_written += xprintf(fp, x, "%d,", cp[i]); } - ch_written += xprintf(fp, x, "%d", p[i]); + ch_written += xprintf(fp, x, "%d", cp[i]); if (trunc) ch_written += xprintf(fp, x, ",..."); else if (bits % 8 != 0) ch_written += xprintf(fp, x, ":%u", (unsigned)(bits % 8)); xputc('>', fp, x); ++ch_written; - ei_free(p); break; } case ERL_SMALL_INTEGER_EXT: diff --git a/lib/erl_interface/src/misc/ei_x_encode.c b/lib/erl_interface/src/misc/ei_x_encode.c index 2da271795f..8e77679d2a 100644 --- a/lib/erl_interface/src/misc/ei_x_encode.c +++ b/lib/erl_interface/src/misc/ei_x_encode.c @@ -117,14 +117,14 @@ int ei_x_encode_binary(ei_x_buff* x, const void* p, int len) return ei_encode_binary(x->buff, &x->index, p, len); } -int ei_x_encode_bitstring(ei_x_buff* x, const void* p, size_t bits) +int ei_x_encode_bitstring(ei_x_buff* x, const char* p, size_t bitoffs, size_t bits) { int i = x->index; - if (ei_encode_bitstring(NULL, &i, p, bits) == -1) + if (ei_encode_bitstring(NULL, &i, p, bitoffs, bits) == -1) return -1; if (!x_fix_buff(x, i)) return -1; - return ei_encode_bitstring(x->buff, &x->index, p, bits); + return ei_encode_bitstring(x->buff, &x->index, p, bitoffs, bits); } int ei_x_encode_long(ei_x_buff* x, long n) diff --git a/lib/erl_interface/src/misc/show_msg.c b/lib/erl_interface/src/misc/show_msg.c index 2d49eb6449..805d69e9b3 100644 --- a/lib/erl_interface/src/misc/show_msg.c +++ b/lib/erl_interface/src/misc/show_msg.c @@ -24,13 +24,6 @@ #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif - -#ifndef SIZE_MAX -# define SIZE_MAX (~((size_t)0)) -#endif #include @@ -464,7 +457,7 @@ static void show_term(const char *termbuf, int *index, FILE *stream) case ERL_BIT_BINARY_EXT: { size_t bits; - ei_decode_bitstring(termbuf, index, NULL, SIZE_MAX, &bits); + ei_decode_bitstring(termbuf, index, NULL, NULL, &bits); fprintf(stream, "#Bits<%lu>", (unsigned long)bits); break; } diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c index 7c9e79f837..385bcdd422 100644 --- a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c +++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c @@ -209,8 +209,9 @@ static void cmd_ei_send_funs(char* buf, int len) erlang_pid pid; ei_x_buff x; erlang_fun fun1, fun2; - unsigned char bitstring[10]; + char* bitstring; size_t bits; + int bitoffs; if (ei_decode_long(buf, &index, &fd) < 0) fail("expected long"); @@ -224,7 +225,7 @@ static void cmd_ei_send_funs(char* buf, int len) fail("expected Fun1"); if (ei_decode_fun(buf, &index, &fun2) < 0) fail("expected Fun2"); - if (ei_decode_bitstring(buf, &index, bitstring, sizeof(bitstring), &bits) < 0) + if (ei_decode_bitstring(buf, &index, &bitstring, &bitoffs, &bits) < 0) fail("expected bitstring"); if (ei_x_new_with_version(&x) < 0) fail("ei_x_new_with_version"); @@ -234,7 +235,7 @@ static void cmd_ei_send_funs(char* buf, int len) fail("encode fun1"); if (ei_x_encode_fun(&x, &fun2) < 0) fail("encode fun2"); - if (ei_x_encode_bitstring(&x, bitstring, bits) < 0) + if (ei_x_encode_bitstring(&x, bitstring, bitoffs, bits) < 0) fail("encode bitstring"); free_fun(&fun1); free_fun(&fun2); diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c index d39970a857..46d6b8f2af 100644 --- a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c +++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c @@ -319,17 +319,18 @@ static void decode_bin(int exp_size, const char* val, int exp_len) static void decode_bits(int exp_size, const char* val, size_t exp_bits) { - char p[1024]; + const char* p; char *buf; size_t bits; + int bitoffs; int size1 = 0; int size2 = 0; int err; message("ei_decode_bitstring should be %d bits", (int)exp_bits); buf = read_packet(NULL); - err = ei_decode_bitstring(buf+1, &size1, NULL, sizeof(p), &bits); - message("err = %d, size = %d, len = %d, expected size = %d, expected bits = %d\n",\ - err,size1, (int)bits, exp_size, (int)exp_bits); + err = ei_decode_bitstring(buf+1, &size1, NULL, &bitoffs, &bits); + message("err = %d, size = %d, bitoffs = %d, bits = %d, expected size = %d, expected bits = %d\n",\ + err,size1, bitoffs, (int)bits, exp_size, (int)exp_bits); if (err != 0) { if (err != -1) { @@ -344,8 +345,12 @@ static void decode_bits(int exp_size, const char* val, size_t exp_bits) fail("number of bits is not correct"); return; } + if (bitoffs != 0) { + fail("non zero bit offset"); + return; + } - err = ei_decode_bitstring(buf+1, &size2, p, sizeof(p), &bits); + err = ei_decode_bitstring(buf+1, &size2, &p, NULL, &bits); message("err = %d, size = %d, len = %d, expected size = %d, expected len = %d\n",\ err,size2, (int)bits, exp_size, (int)exp_bits); if (err != 0) { diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl index d8b0bce3ae..3451d9f503 100644 --- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl +++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl @@ -122,9 +122,29 @@ test_ei_decode_encode(Config) when is_list(Config) -> [send_rec(P, <<16#dec0deb175:B/little>>) || B <- lists:seq(0,48)], + % And last an ugly duckling to test ei_encode_bitstring with bitoffs != 0 + encode_bitstring(P), + runner:recv_eot(P), ok. +encode_bitstring(P) -> + %% Send one bitstring to c-node + Bits = <<16#18f6d4b2907e5c3a1:66>>, + P ! {self(), {command, term_to_binary(Bits, [{minor_version, 2}])}}, + + %% and then receive and verify a number of different sub-bitstrings + receive_sub_bitstring(P, Bits, 0, bit_size(Bits)). + +receive_sub_bitstring(_, _, _, NBits) when NBits < 0 -> + ok; +receive_sub_bitstring(P, Bits, BitOffs, NBits) -> + <<_:BitOffs, Sub:NBits/bits, _/bits>> = Bits, + %%io:format("expecting term_to_binary(~p) = ~p\n", [Sub, term_to_binary(Sub)]), + {_B,Sub} = get_buf_and_term(P), + receive_sub_bitstring(P, Bits, BitOffs+1, NBits - ((NBits div 20)+1)). + + %% ######################################################################## %% diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c index f9c05b2739..85ca6c56e9 100644 --- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c +++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c @@ -42,7 +42,8 @@ typedef struct typedef struct { - char bytes[MAXATOMLEN_UTF8]; + const char* bytes; + unsigned int bitoffs; size_t nbits; }my_bitstring; @@ -128,17 +129,17 @@ struct Type my_atom_type = { int ei_decode_my_bits(const char *buf, int *index, my_bitstring* a) { - return ei_decode_bitstring(buf, index, (a ? a->bytes : NULL), - sizeof(a->bytes), + return ei_decode_bitstring(buf, index, (a ? &a->bytes : NULL), + (a ? &a->bitoffs : NULL), (a ? &a->nbits : NULL)); } int ei_encode_my_bits(char *buf, int *index, my_bitstring* a) { - return ei_encode_bitstring(buf, index, a->bytes, a->nbits); + return ei_encode_bitstring(buf, index, a->bytes, a->bitoffs, a->nbits); } int ei_x_encode_my_bits(ei_x_buff* x, my_bitstring* a) { - return ei_x_encode_bitstring(x, a->bytes, a->nbits); + return ei_x_encode_bitstring(x, a->bytes, a->bitoffs, a->nbits); } struct Type my_bitstring_type = { @@ -264,11 +265,7 @@ void decode_encode(struct Type** tv, int nobj) size1 = 0; err = t->ei_decode_fp(inp, &size1, NULL); if (err != 0) { - if (err != -1) { - fail("decode returned non zero but not -1"); - } else { - fail1("decode '%s' returned non zero", t->name); - } + fail2("decode '%s' returned non zero %d", t->name, err); return; } if (size1 < 1) { @@ -497,6 +494,66 @@ void decode_encode_big(struct Type* t) } +void encode_bitstring(void) +{ + char* packet; + char* inp; + char out_buf[BUFSZ]; + int size; + int err, i; + ei_x_buff arg; + const char* p; + unsigned int bitoffs; + size_t nbits, org_nbits; + + packet = read_packet(NULL); + inp = packet+1; + + size = 0; + err = ei_decode_bitstring(inp, &size, &p, &bitoffs, &nbits); + if (err != 0) { + fail1("ei_decode_bitstring returned non zero %d", err); + return; + } + + /* + * Now send a bunch of different sub-bitstrings back + * encoded both with ei_encode_ and ei_x_encode_. + */ + org_nbits = nbits; + do { + size = 0; + err = ei_encode_bitstring(out_buf, &size, p, bitoffs, nbits); + if (err != 0) { + fail1("ei_encode_bitstring returned non zero %d", err); + return; + } + + ei_x_new(&arg); + err = ei_x_encode_bitstring(&arg, p, bitoffs, nbits); + if (err != 0) { + fail1("ei_x_encode_bitstring returned non zero %d", err); + ei_x_free(&arg); + return; + } + + if (arg.index < 1) { + fail("size is < 1"); + ei_x_free(&arg); + return; + } + + send_buffer(out_buf, size); + send_buffer(arg.buff, arg.index); + ei_x_free(&arg); + + bitoffs++; + nbits -= (nbits / 20) + 1; + } while (nbits < org_nbits); + + free_packet(packet); +} + /* ******************************************************************** */ @@ -568,6 +625,8 @@ TESTCASE(test_ei_decode_encode) decode_encode_one(&my_bitstring_type); } + encode_bitstring(); + report(1); } -- cgit v1.2.3