/* * %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 #include "eidef.h" #include "eiext.h" #include "ei_decode_term.h" #include "putget.h" /* Returns 1 if term is decoded, 0 if term is OK, but not decoded here and -1 if something is wrong. ONLY changes index if term is decoded (return value 1)! */ int ei_decode_ei_term(const char* buf, int* index, ei_term* term) { const char* s = buf + *index, * s0 = s; int len, i, n, sign; char c; double f; if (term == NULL) return -1; c = term->ei_type = get8(s); switch (c) { case ERL_SMALL_INTEGER_EXT: term->value.i_val = get8(s); break; case ERL_INTEGER_EXT: term->value.i_val = get32be(s); break; case ERL_FLOAT_EXT: if (s[30]) return -1; if (sscanf(s, "%lf", &f) != 1) return -1; s += 31; term->value.d_val = f; break; case ERL_ATOM_EXT: len = get16be(s); memcpy(term->value.atom_name, s, len); term->value.atom_name[len] = '\0'; s += len; break; case ERL_REFERENCE_EXT: /* first the nodename */ if (get8(s) != ERL_ATOM_EXT) return -1; len = get16be(s); memcpy(term->value.ref.node, s, len); term->value.ref.node[len] = '\0'; s += len; /* now the numbers: num (4), creation (1) */ term->value.ref.n[0] = get32be(s); term->value.ref.len = 1; term->value.ref.creation = get8(s) & 0x03; break; case ERL_NEW_REFERENCE_EXT: /* first the integer count */ term->value.ref.len = get16be(s); /* then the nodename */ if (get8(s) != ERL_ATOM_EXT) return -1; len = get16be(s); memcpy(term->value.ref.node, s, len); term->value.ref.node[len] = '\0'; s += len; /* creation */ term->value.ref.creation = get8(s) & 0x03; /* finally the id integers */ for (i = 0; (ivalue.ref.len) && (i<3); i++) { term->value.ref.n[i] = get32be(s); } if (term->value.ref.len > 3) { s += 4 * (term->value.ref.len - 3); } break; case ERL_PORT_EXT: if (get8(s) != ERL_ATOM_EXT) return -1; len = get16be(s); memcpy(term->value.port.node, s, len); term->value.port.node[len] = '\0'; term->value.port.id = get32be(s) & 0x0fffffff; /* 28 bits */; term->value.port.creation = get8(s) & 0x03; break; case ERL_PID_EXT: if (get8(s) != ERL_ATOM_EXT) return -1; /* name first */ len = get16be(s); memcpy(term->value.pid.node, s, len); term->value.pid.node[len] = '\0'; s += len; /* now the numbers: num (4), serial (4), creation (1) */ term->value.pid.num = get32be(s) & 0x7fff; /* 15 bits */ term->value.pid.serial = get32be(s) & 0x1fff; /* 13 bits */ term->value.pid.creation = get8(s) & 0x03; /* 2 bits */ break; case ERL_SMALL_TUPLE_EXT: term->arity = get8(s); break; /*return 0;*/ case ERL_LARGE_TUPLE_EXT: term->arity = get32be(s); break; /*return 0;*/ case ERL_NIL_EXT: term->arity = 0; break; case ERL_STRING_EXT: term->size = get16be(s); return 0; case ERL_LIST_EXT: term->arity = get32be(s); break; /*return 0;*/ case ERL_BINARY_EXT: term->size = get32be(s); return 0; case ERL_SMALL_BIG_EXT: if ((term->arity = get8(s)) != 4) return -1; sign = get8(s); /* Little Endian, and n always positive, except for LONG_MIN */ n = get32le(s); if (sign) { /* check for overflow */ if ((n - 1) < 0) return -1; n = -n; } else { /* check for overflow */ if (n < 0) return -1; } break; case ERL_LARGE_BIG_EXT: return 0; case ERL_PASS_THROUGH: return 0; case ERL_NEW_CACHE: return -1; case ERL_CACHED_ATOM: return -1; default: return -1; } *index += s-s0; return 1; }