aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface/src/decode
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2019-04-26 19:43:53 +0200
committerSverker Eriksson <[email protected]>2019-04-26 19:43:53 +0200
commit01aa8b82dd0f8229355ffd2bb2bc8e8f496d2df6 (patch)
tree0a3ae48dfe7f442aa138d7c06fbf5444e9f7c8b6 /lib/erl_interface/src/decode
parent8f6d45ddc8b2b12376c252a30b267a822cad171a (diff)
downloadotp-01aa8b82dd0f8229355ffd2bb2bc8e8f496d2df6.tar.gz
otp-01aa8b82dd0f8229355ffd2bb2bc8e8f496d2df6.tar.bz2
otp-01aa8b82dd0f8229355ffd2bb2bc8e8f496d2df6.zip
erl_interface: Tweak bit string encode/decode API
to support zero copy decoding and bit offset arguments for future unaligned bit strings.
Diffstat (limited to 'lib/erl_interface/src/decode')
-rw-r--r--lib/erl_interface/src/decode/decode_binary.c61
-rw-r--r--lib/erl_interface/src/decode/decode_skip.c10
2 files changed, 32 insertions, 39 deletions
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 <stdint.h>
-#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: