diff options
Diffstat (limited to 'lib/erl_interface/src/encode')
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; +} + |