aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface/src/encode
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/erl_interface/src/encode
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/erl_interface/src/encode')
-rw-r--r--lib/erl_interface/src/encode/eicode.h69
-rw-r--r--lib/erl_interface/src/encode/encode_atom.c51
-rw-r--r--lib/erl_interface/src/encode/encode_big.c84
-rw-r--r--lib/erl_interface/src/encode/encode_bignum.c81
-rw-r--r--lib/erl_interface/src/encode/encode_binary.c41
-rw-r--r--lib/erl_interface/src/encode/encode_boolean.c47
-rw-r--r--lib/erl_interface/src/encode/encode_char.c38
-rw-r--r--lib/erl_interface/src/encode/encode_double.c42
-rw-r--r--lib/erl_interface/src/encode/encode_fun.c82
-rw-r--r--lib/erl_interface/src/encode/encode_list_header.c45
-rw-r--r--lib/erl_interface/src/encode/encode_long.c64
-rw-r--r--lib/erl_interface/src/encode/encode_longlong.c103
-rw-r--r--lib/erl_interface/src/encode/encode_pid.c52
-rw-r--r--lib/erl_interface/src/encode/encode_port.c51
-rw-r--r--lib/erl_interface/src/encode/encode_ref.c59
-rw-r--r--lib/erl_interface/src/encode/encode_string.c77
-rw-r--r--lib/erl_interface/src/encode/encode_trace.c36
-rw-r--r--lib/erl_interface/src/encode/encode_tuple_header.c49
-rw-r--r--lib/erl_interface/src/encode/encode_ulong.c57
-rw-r--r--lib/erl_interface/src/encode/encode_ulonglong.c94
-rw-r--r--lib/erl_interface/src/encode/encode_version.c35
21 files changed, 1257 insertions, 0 deletions
diff --git a/lib/erl_interface/src/encode/eicode.h b/lib/erl_interface/src/encode/eicode.h
new file mode 100644
index 0000000000..cf008b7fa9
--- /dev/null
+++ b/lib/erl_interface/src/encode/eicode.h
@@ -0,0 +1,69 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#ifndef _EICODE_H
+#define _EICODE_H
+
+/*
+ * The following functions are used to encode from c native types directly into
+ * Erlang external format. To use them, you need
+ *
+ * - a destination buffer
+ * - an index counter
+ * - some data
+ * - an idea of how you want to represent the data as an Erlang term.
+ *
+ * You can encode exactly one (1) term into the buffer if you are
+ * going to transmit it to Erlang. Do the following:
+ *
+ * 1. Set your index to 0
+ * 2. Encode the version into the buffer: ei_encode_version(buf,&index);
+ * The function has now advanced index so the next item can be encoded.
+ * 3. Encode your term:
+ *
+ * Encoding non-compound types (i.e. not lists or tuples) is
+ * straightforward. Just do it!
+ *
+ * Encoding tuples is done by first encoding the tuple header (it
+ * contains the arity) and then encoding the tuple elements in
+ * sequence.
+ *
+ * Encoding lists is done by first encoding the list header (it
+ * contains the arity) and then encoding the list elements in
+ * sequence, and finally encoding an empty list.
+ *
+ * After all this, the index counter will tell you how much buffer you
+ * used. If you really need to know in advance how big the buffer
+ * should be, go through the same steps but with a NULL buffer. No
+ * attempt will be made to modify the buffer, but index will be
+ * updated as though you really did encode something.
+ */
+
+/* encode the given object into buf[index] as 'type'. 0 is
+ * returned and index is updated to the position for the next item. if
+ * buf == NULL, no data is actually copied, but index is updated to
+ * indicate the number of bytes that would have been necessary.
+ */
+
+/* FIXME where do we put these..... */
+
+erlang_big *ei_alloc_big(int arity);
+void ei_free_big(erlang_big *b);
+
+
+#endif /* _EICODE_H */
diff --git a/lib/erl_interface/src/encode/encode_atom.c b/lib/erl_interface/src/encode/encode_atom.c
new file mode 100644
index 0000000000..69f2d1451c
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_atom.c
@@ -0,0 +1,51 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_atom(char *buf, int *index, const char *p)
+{
+ return ei_encode_atom_len(buf, index, p, strlen(p));
+}
+
+int ei_encode_atom_len(char *buf, int *index, const char *p, int len)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ /* This function is documented to truncate at MAXATOMLEN (256) */
+ if (len > MAXATOMLEN)
+ len = MAXATOMLEN;
+
+ if (!buf) s += 3;
+ else {
+ put8(s,ERL_ATOM_EXT);
+ put16be(s,len);
+
+ memmove(s,p,len); /* unterminated string */
+ }
+ s += len;
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_big.c b/lib/erl_interface/src/encode/encode_big.c
new file mode 100644
index 0000000000..25abf424b7
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_big.c
@@ -0,0 +1,84 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+#include "ei_x_encode.h"
+
+int ei_encode_big(char *buf, int *index, erlang_big* big) {
+ unsigned char *s = (unsigned char *)buf + *index;
+ unsigned char *s0 = s;
+ unsigned int digit_bytes = big->arity;
+ unsigned int n = (digit_bytes+1)/2;
+
+ if (digit_bytes < 256) {
+ if (buf) {
+ put8(s, ERL_SMALL_BIG_EXT);
+ put8(s, digit_bytes);
+ } else {
+ s += 2;
+ }
+ } else {
+ if (buf) {
+ put8(s, ERL_LARGE_BIG_EXT);
+ put32be(s, digit_bytes);
+ } else {
+ s += 5;
+ }
+ }
+
+ if (buf) {
+ int i;
+ unsigned char hi, lo;
+ unsigned short *dt = big->digits;
+ put8(s, big->is_neg);
+
+ for (i = 0; i < n; ++i) {
+
+ hi = (unsigned char) (dt[i] >> 8);
+ lo = (unsigned char) (dt[i]);
+
+ s[i*2] = lo;
+ if ((i*2 + 1) < digit_bytes) {
+ s[i*2 + 1] = hi;
+ }
+ }
+
+ } else {
+ s ++; /* skip sign bit */
+ }
+
+ s += digit_bytes;
+
+ *index += s-s0;
+
+ return 0;
+}
+
+int ei_x_encode_big(ei_x_buff* x, erlang_big* big) {
+ int i = x->index;
+
+ ei_encode_big(NULL, &i, big);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_big(x->buff, &x->index, big);
+}
+
diff --git a/lib/erl_interface/src/encode/encode_bignum.c b/lib/erl_interface/src/encode/encode_bignum.c
new file mode 100644
index 0000000000..6850cb86a6
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_bignum.c
@@ -0,0 +1,81 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "eidef.h"
+
+#if defined(HAVE_GMP_H) && defined(HAVE_LIBGMP)
+
+#include <gmp.h>
+
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+#include "ei_x_encode.h"
+
+int ei_encode_bignum(char *buf, int *index, mpz_t obj)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+ size_t count;
+ int mpz_sign = mpz_sgn(obj);
+
+ /*
+ * FIXME we could code into ERL_[SMALL_]INTEGER_EXT but to make
+ * this code simple for now we always code into ERL_SMALL_BIG_EXT
+ */
+
+ if (mpz_sign == 0) { /* Special case, bignum is zero */
+ if (!buf) s += 2;
+ else {
+ put8(s,ERL_SMALL_INTEGER_EXT);
+ put8(s,0);
+ }
+ } else {
+
+ if (!buf) {
+ int numb = 8; /* # bits in each external format limb */
+ s += (mpz_sizeinbase(obj, 2) + numb-1) / numb;
+ } else {
+ char *arityp;
+
+ put8(s,ERL_LARGE_BIG_EXT);
+ arityp = s; /* fill in later */
+ s += 4;
+ put8(s, mpz_sign == 1); /* save sign separately */
+ mpz_export(s, &count, -1, 1, 0, 0, obj);
+ s += count;
+ put32le(arityp, count);
+ }
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
+int ei_x_encode_bignum(ei_x_buff* x, mpz_t n)
+{
+ int i = x->index;
+ ei_encode_bignum(NULL, &i, n);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_bignum(x->buff, &x->index, n);
+}
+
+#endif /* HAVE_GMP_H && HAVE_LIBGMP */
diff --git a/lib/erl_interface/src/encode/encode_binary.c b/lib/erl_interface/src/encode/encode_binary.c
new file mode 100644
index 0000000000..67a4dc1219
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_binary.c
@@ -0,0 +1,41 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_binary(char *buf, int *index, const void *p, long len)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if (!buf) s += 5;
+ else {
+ put8(s,ERL_BINARY_EXT);
+ put32be(s,len);
+ memmove(s,p,len);
+ }
+ s += len;
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_boolean.c b/lib/erl_interface/src/encode/encode_boolean.c
new file mode 100644
index 0000000000..51a166bea5
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_boolean.c
@@ -0,0 +1,47 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_boolean(char *buf, int *index, int p)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+ char *val;
+ int len;
+
+ val = p ? "true" : "false";
+ len = strlen(val);
+
+ if (!buf) s += 3;
+ else {
+ put8(s,ERL_ATOM_EXT);
+ put16be(s,len);
+
+ memmove(s,val,len); /* unterminated string */
+ }
+ s += len;
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_char.c b/lib/erl_interface/src/encode/encode_char.c
new file mode 100644
index 0000000000..a7d27c5261
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_char.c
@@ -0,0 +1,38 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_char(char *buf, int *index, char p)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if (!buf) s += 2;
+ else {
+ put8(s,ERL_SMALL_INTEGER_EXT);
+ put8(s,(p & 0xff));
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_double.c b/lib/erl_interface/src/encode/encode_double.c
new file mode 100644
index 0000000000..53f3d52ba6
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_double.c
@@ -0,0 +1,42 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <stdio.h>
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_double(char *buf, int *index, double p)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if (!buf) s ++;
+ else {
+ put8(s,ERL_FLOAT_EXT);
+ memset(s, 0, 31);
+ sprintf(s, "%.20e", p);
+ }
+ s += 31;
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_fun.c b/lib/erl_interface/src/encode/encode_fun.c
new file mode 100644
index 0000000000..54ee2083d6
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_fun.c
@@ -0,0 +1,82 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_fun(char *buf, int *index, const erlang_fun *p)
+{
+ int ix = *index;
+
+ if (p->arity == -1) {
+ /* ERL_FUN_EXT */
+ if (buf != NULL) {
+ char* s = buf + ix;
+ put8(s, ERL_FUN_EXT);
+ put32be(s, p->n_free_vars);
+ }
+ ix += sizeof(char) + 4;
+ if (ei_encode_pid(buf, &ix, &p->pid) < 0)
+ return -1;
+ if (ei_encode_atom(buf, &ix, p->module) < 0)
+ return -1;
+ if (ei_encode_long(buf, &ix, p->index) < 0)
+ return -1;
+ if (ei_encode_long(buf, &ix, p->uniq) < 0)
+ return -1;
+ if (buf != NULL)
+ memcpy(buf + ix, p->free_vars, p->free_var_len);
+ ix += p->free_var_len;
+ } else {
+ char *size_p;
+ /* ERL_NEW_FUN_EXT */
+ if (buf != NULL) {
+ char* s = buf + ix;
+ put8(s, ERL_NEW_FUN_EXT);
+ size_p = s;
+ s += 4;
+ put8(s, p->arity);
+ memcpy(s, p->md5, sizeof(p->md5));
+ s += sizeof(p->md5);
+ put32be(s, p->index);
+ put32be(s, p->n_free_vars);
+ } else
+ size_p = NULL;
+ ix += 1 + 4 + 1 + sizeof(p->md5) + 4 + 4;
+ if (ei_encode_atom(buf, &ix, p->module) < 0)
+ return -1;
+ if (ei_encode_long(buf, &ix, p->old_index) < 0)
+ return -1;
+ if (ei_encode_long(buf, &ix, p->uniq) < 0)
+ return -1;
+ if (ei_encode_pid(buf, &ix, &p->pid) < 0)
+ return -1;
+ if (buf != NULL)
+ memcpy(buf + ix, p->free_vars, p->free_var_len);
+ ix += p->free_var_len;
+ if (size_p != NULL) {
+ int sz = buf + ix - size_p;
+ put32be(size_p, sz);
+ }
+ }
+ *index = ix;
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_list_header.c b/lib/erl_interface/src/encode/encode_list_header.c
new file mode 100644
index 0000000000..27da70ae15
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_list_header.c
@@ -0,0 +1,45 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_list_header(char *buf, int *index, int arity)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if (arity < 0) return -1;
+ else if (arity > 0) {
+ if (!buf) s += 5;
+ else {
+ put8(s,ERL_LIST_EXT);
+ put32be(s,arity);
+ }
+ }
+ else {
+ /* empty list */
+ if (!buf) s++;
+ else put8(s,ERL_NIL_EXT);
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/encode/encode_long.c b/lib/erl_interface/src/encode/encode_long.c
new file mode 100644
index 0000000000..d616bb6e47
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_long.c
@@ -0,0 +1,64 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+#define abs(p) (((p)<0) ? -(p) : p)
+
+/* long -> erl_integer */
+/* note that this is the only place where data is stored Little Endian */
+
+#ifndef EI_64BIT
+int ei_encode_long(char *buf, int *index, long p)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if ((p < 256) && (p >= 0)) {
+ if (!buf) s += 2;
+ else {
+ put8(s,ERL_SMALL_INTEGER_EXT);
+ put8(s,(p & 0xff));
+ }
+ }
+ else if ((p <= ERL_MAX) && (p >= ERL_MIN)) {
+ /* FIXME: Non optimal, could use (p <= LONG_MAX) && (p >= LONG_MIN)
+ and skip next case */
+ if (!buf) s += 5;
+ else {
+ put8(s,ERL_INTEGER_EXT);
+ put32be(s,p);
+ }
+ }
+ else {
+ if (!buf) s += 7;
+ else {
+ put8(s,ERL_SMALL_BIG_EXT);
+ put8(s,4); /* len = four bytes */
+ put8(s, p < 0); /* save sign separately */
+ put32le(s, abs(p)); /* OBS: Little Endian, and p now positive */
+ }
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+#endif /* EI_64BIT */
diff --git a/lib/erl_interface/src/encode/encode_longlong.c b/lib/erl_interface/src/encode/encode_longlong.c
new file mode 100644
index 0000000000..aff24e2478
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_longlong.c
@@ -0,0 +1,103 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+#include "ei_x_encode.h"
+
+#define abs(p) (((p)<0) ? -(p) : p)
+
+/* long -> erl_integer */
+/* note that this is the only place where data is stored Little Endian */
+
+/*
+ * For some 64 bit operations on some operating systems code
+ * compiled with GNU cc depends on "libgcc" for some 64 bit
+ * operations missing in hardware (or because of gcc bugs).
+ * If user code was linked together with the ei lib
+ * using other linkers than GNU ld this may cause problems.
+ * We moved ei_x_encode_longlong() here from "ei_x_encode.c"
+ * to limit this problem to users that actually use the ei
+ * longlong operations, not all ei_x users.
+ */
+int ei_x_encode_longlong(ei_x_buff* x, EI_LONGLONG n)
+{
+ int i = x->index;
+ ei_encode_longlong(NULL, &i, n);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_longlong(x->buff, &x->index, n);
+}
+
+#ifdef EI_64BIT
+int ei_encode_long(char *buf, int *index, long p)
+{
+ return ei_encode_longlong(buf, index, p);
+}
+#endif
+
+int ei_encode_longlong(char *buf, int *index, EI_LONGLONG p)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if ((p < 256) && (p >= 0)) {
+ if (!buf) s += 2;
+ else {
+ put8(s,ERL_SMALL_INTEGER_EXT);
+ put8(s,(p & 0xff));
+ }
+ } else if ((p <= ERL_MAX) && (p >= ERL_MIN)) {
+ /* FIXME: Non optimal, could use (p <= LONG_MAX) && (p >= LONG_MIN)
+ and skip next case */
+ if (!buf) s += 5;
+ else {
+ put8(s,ERL_INTEGER_EXT);
+ put32be(s,p);
+ }
+ } else {
+ /* We know 28-64 bits needed, i.e four to eight bytes */
+ EI_ULONGLONG up = abs(p); /* FIXME name uabs(x) not to confuse with abs */
+ if (buf) {
+ char *arityp;
+ int arity = 0;
+
+ put8(s,ERL_SMALL_BIG_EXT);
+ arityp = s++; /* fill in later */
+ put8(s, p < 0); /* save sign separately */
+ while (up) {
+ *s++ = up & 0xff; /* take lowest byte */
+ up >>= 8; /* shift unsigned */
+ arity++;
+ }
+ put8(arityp,arity);
+ } else {
+ s += 3; /* Type, arity and sign */
+ while (up) {
+ s++; /* take lowest byte */
+ up >>= 8; /* shift unsigned */
+ }
+ }
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_pid.c b/lib/erl_interface/src/encode/encode_pid.c
new file mode 100644
index 0000000000..ee7f235c17
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_pid.c
@@ -0,0 +1,52 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_pid(char *buf, int *index, const erlang_pid *p)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+ int len = strlen(p->node);
+
+ if (!buf) s += 13 + len;
+ else {
+ put8(s,ERL_PID_EXT);
+
+ /* first the nodename */
+ put8(s,ERL_ATOM_EXT);
+
+ put16be(s,len);
+
+ memmove(s, p->node, len);
+ s += len;
+
+ /* now the integers */
+ put32be(s,p->num & 0x7fff); /* 15 bits */
+ put32be(s,p->serial & 0x1fff); /* 13 bits */
+ put8(s,(p->creation & 0x03)); /* 2 bits */
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_port.c b/lib/erl_interface/src/encode/encode_port.c
new file mode 100644
index 0000000000..fbbb33182e
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_port.c
@@ -0,0 +1,51 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_port(char *buf, int *index, const erlang_port *p)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+ int len = strlen(p->node);
+
+ if (!buf) s += 9 + len;
+ else {
+ put8(s,ERL_PORT_EXT);
+
+ /* first the nodename */
+ put8(s,ERL_ATOM_EXT);
+
+ put16be(s,len);
+
+ memmove(s, p->node, len);
+ s += len;
+
+ /* now the integers */
+ put32be(s,p->id & 0x0fffffff /* 28 bits */);
+ put8(s,(p->creation & 0x03));
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_ref.c b/lib/erl_interface/src/encode/encode_ref.c
new file mode 100644
index 0000000000..292b452864
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_ref.c
@@ -0,0 +1,59 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_ref(char *buf, int *index, const erlang_ref *p)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+ int len = strlen(p->node);
+ int i;
+
+ /* Always encode as an extended reference; all participating parties
+ are now expected to be able to decode extended references. */
+ if (!buf) s += 1 + 2 + (3+len) + p->len*4 + 1;
+ else {
+ put8(s,ERL_NEW_REFERENCE_EXT);
+
+ /* first, number of integers */
+ put16be(s, p->len);
+
+ /* then the nodename */
+ put8(s,ERL_ATOM_EXT);
+
+ put16be(s,len);
+
+ memmove(s, p->node, len);
+ s += len;
+
+ /* now the integers */
+ put8(s,(p->creation & 0x03));
+ for (i = 0; i < p->len; i++)
+ put32be(s,p->n[i]);
+
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_string.c b/lib/erl_interface/src/encode/encode_string.c
new file mode 100644
index 0000000000..1d342cb605
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_string.c
@@ -0,0 +1,77 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+
+int ei_encode_string(char *buf, int *index, const char *p)
+{
+ return ei_encode_string_len(buf, index, p, strlen(p));
+}
+
+int ei_encode_string_len(char *buf, int *index, const char *p, int len)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+ int i;
+
+ if (len == 0) {
+
+ if (!buf) {
+ s += 1;
+ } else {
+ put8(s,ERL_NIL_EXT);
+ }
+
+ } else if (len <= 0xffff) {
+
+ if (!buf) {
+ s += 3;
+ } else {
+ put8(s,ERL_STRING_EXT);
+ put16be(s,len);
+ memmove(s,p,len); /* unterminated string */
+ }
+ s += len;
+
+ } else {
+
+ if (!buf) {
+ s += 5 + (2*len) + 1;
+ } else {
+ /* strings longer than 65535 are encoded as lists */
+ put8(s,ERL_LIST_EXT);
+ put32be(s,len);
+
+ for (i=0; i<len; i++) {
+ put8(s,ERL_SMALL_INTEGER_EXT);
+ put8(s,p[i]);
+ }
+ put8(s,ERL_NIL_EXT);
+ }
+
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_trace.c b/lib/erl_interface/src/encode/encode_trace.c
new file mode 100644
index 0000000000..de46f7fae8
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_trace.c
@@ -0,0 +1,36 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include "eidef.h"
+#include "putget.h"
+
+int ei_encode_trace(char *buf, int *index, const erlang_trace *p)
+{
+ /* { Flags, Label, Serial, FromPid, Prev } */
+ ei_encode_tuple_header(buf,index,5);
+ ei_encode_long(buf,index,p->flags);
+ ei_encode_long(buf,index,p->label);
+ ei_encode_long(buf,index,p->serial);
+ ei_encode_pid(buf,index,&p->from);
+ ei_encode_long(buf,index,p->prev);
+
+ /* index is updated by the functions we called */
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_tuple_header.c b/lib/erl_interface/src/encode/encode_tuple_header.c
new file mode 100644
index 0000000000..97a3d1f808
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_tuple_header.c
@@ -0,0 +1,49 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_encode_tuple_header(char *buf, int *index, int arity)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if (arity < 0) return -1;
+
+ if (arity <= 0xff) {
+ if (!buf) s += 2;
+ else {
+ put8(s,ERL_SMALL_TUPLE_EXT);
+ put8(s,arity);
+ }
+ }
+ else {
+ if (!buf) s += 5;
+ else {
+ put8(s,ERL_LARGE_TUPLE_EXT);
+ put32be(s,arity);
+ }
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_ulong.c b/lib/erl_interface/src/encode/encode_ulong.c
new file mode 100644
index 0000000000..c4ff34e493
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_ulong.c
@@ -0,0 +1,57 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+#ifndef EI_64BIT
+int ei_encode_ulong(char *buf, int *index, unsigned long p)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if (p > ERL_MAX) {
+ if (!buf) s += 7;
+ else {
+ put8(s,ERL_SMALL_BIG_EXT);
+ put8(s,4); /* len = four bytes */
+ put8(s, 0); /* save sign separately */
+ put32le(s,p); /* OBS: Little Endian, and p now positive */
+ }
+ }
+ else if ((p < 256) && (p >= 0)) {
+ if (!buf) s += 2;
+ else {
+ put8(s,ERL_SMALL_INTEGER_EXT);
+ put8(s,(p & 0xff));
+ }
+ }
+ else {
+ if (!buf) s += 5;
+ else {
+ put8(s,ERL_INTEGER_EXT);
+ put32be(s,p);
+ }
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+#endif /* EI_64BIT */
diff --git a/lib/erl_interface/src/encode/encode_ulonglong.c b/lib/erl_interface/src/encode/encode_ulonglong.c
new file mode 100644
index 0000000000..0f21af2a91
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_ulonglong.c
@@ -0,0 +1,94 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+#include "ei_x_encode.h"
+
+/*
+ * For some 64 bit operations on some operating systems code
+ * compiled with GNU cc depends on "libgcc" for some 64 bit
+ * operations missing in hardware (or because of gcc bugs).
+ * If user code was linked together with the ei lib
+ * using other linkers than GNU ld this may cause problems.
+ * We moved ei_x_encode_ulonglong() here from "ei_x_encode.c"
+ * to limit this problem to users that actually use the ei
+ * longlong operations, not all ei_x users.
+ */
+int ei_x_encode_ulonglong(ei_x_buff* x, EI_ULONGLONG n)
+{
+ int i = x->index;
+ ei_encode_ulonglong(NULL, &i, n);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_ulonglong(x->buff, &x->index, n);
+}
+
+#ifdef EI_64BIT
+int ei_encode_ulong(char *buf, int *index, unsigned long p)
+{
+ return ei_encode_ulonglong(buf, index, p);
+}
+#endif
+
+int ei_encode_ulonglong(char *buf, int *index, EI_ULONGLONG p)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if ((p < 256) && (p >= 0)) {
+ if (!buf) s += 2;
+ else {
+ put8(s,ERL_SMALL_INTEGER_EXT);
+ put8(s,(p & 0xff));
+ }
+ } else if (p <= ERL_MAX) {
+ if (!buf) s += 5;
+ else {
+ put8(s,ERL_INTEGER_EXT);
+ put32be(s,p);
+ }
+ } else {
+ /* We know 28-64 bits needed, i.e four to eight bytes */
+ if (buf) {
+ char *arityp;
+ int arity = 0;
+ put8(s,ERL_SMALL_BIG_EXT);
+ arityp = s++; /* fill in later */
+ put8(s, 0); /* save sign separately */
+ while (p) {
+ *s++ = p & 0xff; /* take lowest byte */
+ p >>= 8; /* shift unsigned */
+ arity++;
+ }
+ put8(arityp,arity);
+ } else {
+ s += 3; /* Type, arity and sign */
+ while (p) {
+ s++; /* take lowest byte */
+ p >>= 8; /* shift unsigned */
+ }
+ }
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/encode/encode_version.c b/lib/erl_interface/src/encode/encode_version.c
new file mode 100644
index 0000000000..3fd9fdabd4
--- /dev/null
+++ b/lib/erl_interface/src/encode/encode_version.c
@@ -0,0 +1,35 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+/* add the version identifier to the start of the buffer */
+int ei_encode_version(char *buf, int *index)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+
+ if (!buf) s ++;
+ else put8(s,(unsigned char)ERL_VERSION_MAGIC);
+ *index += s-s0;
+
+ return 0;
+}
+