erl_marshal.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 1,923 行 · 第 1/4 页

C
1,923
字号
      CMP_EXT_INT32_BE(tmp1, tmp2);      /* ... then ids ... */      tmp1 -= 4; tmp2 -= 4;      CMP_EXT_INT32_BE(tmp1, tmp2);      /* ... then node names ... */      ret = cmp_exe2(&n1, &n2);      if (ret != 0)	  return ret;      /* ... and then finaly creations. */      tmp1 += 8; tmp2 += 8;      if (*tmp1 != *tmp2)	  return *tmp1 < *tmp2 ? -1 : 1;      return 0;    }    case ERL_PORT_EXT:      /* First compare node names ... */      if (**e1 != ERL_ATOM_EXT || **e2 != ERL_ATOM_EXT)	  return CMP_EXT_ERROR_CODE;      ret = cmp_exe2(e1, e2);      *e1 += 5; *e2 += 5;      if (ret != 0)	  return ret;      /* ... then creations ... */      tmp1 = *e1 - 1; tmp2 = *e2 - 1;      if (*tmp1 != *tmp2)	  return *tmp1 < *tmp2 ? -1 : 1;      /* ... and then finaly ids. */      tmp1 -= 4; tmp2 -= 4;      CMP_EXT_INT32_BE(tmp1, tmp2);      return 0;    case ERL_NIL_EXT: return 0;    case ERL_LIST_EXT:      i = (**e1 << 24) | ((*e1)[1] << 16) |((*e1)[2] << 8) | (*e1)[3];      *e1 += 4;      j = (**e2 << 24) | ((*e2)[1] << 16) |((*e2)[2] << 8) | (*e2)[3];      *e2 += 4;      if ( i == j && j == 0 ) return 0;      min = (i < j) ? i : j;      k = 0;      while (1) {	if (k++ == min)	  return compare_top_ext(e1 , e2);	if ((ret = compare_top_ext(e1 , e2)) == 0) 	  continue;	return ret;      }    case ERL_STRING_EXT:      i = (**e1 << 8) | ((*e1)[1]);      *e1 += 2;      j = (**e2 << 8) | ((*e2)[1]);      *e2 += 2;      ret = cmpbytes(*e1, i, *e2, j);      *e1 += i;      *e2 += j;      return ret;    case ERL_SMALL_TUPLE_EXT:      i = *(*e1)++; 	j = *(*e2)++;      if (i < j) return -1;      if (j > j ) return 1;      while (i--) {	if ((j = compare_top_ext(e1, e2))) return j;      }      return 0;    case ERL_LARGE_TUPLE_EXT:      i = (**e1 << 24) | ((*e1)[1]) << 16| ((*e1)[2]) << 8| ((*e1)[3]) ;	      *e1 += 4;      j = (**e2 << 24) | ((*e2)[1]) << 16| ((*e2)[2]) << 8| ((*e2)[3]) ;	      *e2 += 4;      if (i < j) return -1;      if (j > j ) return 1;      while (i--) {	if ((j = compare_top_ext(e1, e2))) return j;      }      return 0;    case ERL_FLOAT_EXT:      if (sscanf((char *) *e1, "%lf", &ff1) != 1)	return -1;      *e1 += 31;      if (sscanf((char *) *e2, "%lf", &ff2) != 1)	return -1;      *e2 += 31;      return cmp_floats(ff1,ff2);    case ERL_BINARY_EXT:      i = (**e1 << 24) | ((*e1)[1] << 16) |((*e1)[2] << 8) | (*e1)[3];      *e1 += 4;      j = (**e2 << 24) | ((*e2)[1] << 16) |((*e2)[2] << 8) | (*e2)[3];      *e2 += 4;      ret = cmpbytes(*e1, i , *e2 , j);      *e1 += i; *e2 += j;      return ret;    case ERL_FUN_EXT:  /* FIXME: */    case ERL_NEW_FUN_EXT:  /* FIXME: */      return -1;    default:      return cmpbytes(*e1, 1, *e2, 1);    } /* switch */  } /* cmp_exe2 *//* Number compare */static int cmp_floats(double f1, double f2){#if defined(VXWORKS) && CPU == PPC860      return erl_fp_compare((unsigned *) &f1, (unsigned *) &f2);#else      if (f1<f2) return -1;      else if (f1>f2) return 1;      else return 0;#endif}static INLINE double to_float(long l) {    double f;#if defined(VXWORKS) && CPU == PPC860    erl_long_to_fp(l, (unsigned *) &f);#else    f = l;#endif    return f;}static int cmp_small_big(unsigned char**e1, unsigned char **e2){    int i1,i2;    int t2;    int n2;    long l1;    int res;    erlang_big *b1,*b2;    i1 = i2 = 0;    if ( ei_decode_long(*e1,&i1,&l1) < 0 ) return -1;        ei_get_type(*e2,&i2,&t2,&n2);        /* any small will fit in two digits */    if ( (b1 = ei_alloc_big(2)) == NULL ) return -1;    if ( ei_small_to_big(l1,b1) < 0 ) {        ei_free_big(b1);        return -1;    }        if ( (b2 = ei_alloc_big(n2)) == NULL ) {        ei_free_big(b1);        return 1;    }    if ( ei_decode_big(*e2,&i2,b2) < 0 ) {        ei_free_big(b1);        ei_free_big(b2);        return 1;    }        res = ei_big_comp(b1,b2);        ei_free_big(b1);    ei_free_big(b2);    return res;}static int cmp_small_float(unsigned char**e1, unsigned char **e2){    int i1,i2;    long l1;    double f1,f2;    /* small -> float -> float_comp */    i1 = i2 = 0;    if ( ei_decode_long(*e1,&i1,&l1) < 0 ) return -1;    if ( ei_decode_double(*e2,&i2,&f2) < 0 ) return 1;        f1 = to_float(l1);    return cmp_floats(f1,f2);}static int cmp_float_big(unsigned char**e1, unsigned char **e2){    int res;    int i1,i2;    int t2,n2;    double f1,f2;    erlang_big *b2;        /* big -> float if overflow return big sign else float_comp */        i1 = i2 = 0;    if ( ei_decode_double(*e1,&i1,&f1) < 0 ) return -1;        if (ei_get_type(*e2,&i2,&t2,&n2) < 0) return 1;    if ((b2 = ei_alloc_big(n2)) == NULL) return 1;    if (ei_decode_big(*e2,&i2,b2) < 0) return 1;        /* convert the big to float */    if ( ei_big_to_double(b2,&f2) < 0 ) {        /* exception look at the sign */        res = b2->is_neg ? 1 : -1;        ei_free_big(b2);        return res;    }        ei_free_big(b2);    return cmp_floats(f1,f2);}static int cmp_small_small(unsigned char**e1, unsigned char **e2){    int i1,i2;    long l1,l2;    i1 = i2 = 0;    if ( ei_decode_long(*e1,&i1,&l1) < 0 ) {        fprintf(stderr,"Failed to decode 1\r\n");        return -1;    }    if ( ei_decode_long(*e2,&i2,&l2) < 0 ) {        fprintf(stderr,"Failed to decode 2\r\n");        return 1;    }        if ( l1 < l2 ) return -1;    else if ( l1 > l2 ) return 1;    else return 0;}static int cmp_float_float(unsigned char**e1, unsigned char **e2){    int i1,i2;    double f1,f2;    i1 = i2 = 0;    if ( ei_decode_double(*e1,&i1,&f1) < 0 ) return -1;    if ( ei_decode_double(*e2,&i2,&f2) < 0 ) return 1;        return cmp_floats(f1,f2);}static int cmp_big_big(unsigned char**e1, unsigned char **e2){    int res;    int i1,i2;    int t1,t2;    int n1,n2;    erlang_big *b1,*b2;    i1 = i2 = 0;    ei_get_type(*e1,&i1,&t1,&n1);    ei_get_type(*e2,&i2,&t2,&n2);        b1 = ei_alloc_big(n1);    b2 = ei_alloc_big(n2);        ei_decode_big(*e1,&i1,b1);    ei_decode_big(*e2,&i2,b2);        res = ei_big_comp(b1,b2);        ei_free_big(b1);    ei_free_big(b2);    return res;}static int cmp_number(unsigned char**e1, unsigned char **e2){    switch (CMP_NUM_CODE(**e1,**e2)) {      case SMALL_BIG:        /* fprintf(stderr,"compare small_big\r\n"); */        return cmp_small_big(e1,e2);      case BIG_SMALL:        /* fprintf(stderr,"compare sbig_small\r\n"); */        return -cmp_small_big(e2,e1);      case SMALL_FLOAT:        /* fprintf(stderr,"compare small_float\r\n"); */        return cmp_small_float(e1,e2);              case FLOAT_SMALL:        /* fprintf(stderr,"compare float_small\r\n"); */        return -cmp_small_float(e2,e1);      case FLOAT_BIG:        /* fprintf(stderr,"compare float_big\r\n"); */        return cmp_float_big(e1,e2);      case BIG_FLOAT:        /* fprintf(stderr,"compare big_float\r\n"); */        return -cmp_float_big(e2,e1);      case SMALL_SMALL:        /* fprintf(stderr,"compare small_small\r\n"); */        return cmp_small_small(e1,e2);      case FLOAT_FLOAT:        /* fprintf(stderr,"compare float_float\r\n"); */        return cmp_float_float(e1,e2);      case BIG_BIG:        /* fprintf(stderr,"compare big_big\r\n"); */        return cmp_big_big(e1,e2);      default:        /* should never get here ... */        /* fprintf(stderr,"compare standard\r\n"); */        return cmp_exe2(e1,e2);    }}/*  * If the arrays are of the same type, then we * have to do a real compare. *//*  * COMPARE TWO encoded BYTE ARRAYS e1 and e2. * Return: -1 if e1 < e2 *          0 if e1 == e2  *          1 if e2 > e1    */static int compare_top_ext(unsigned char**e1, unsigned char **e2){  if (**e1 == ERL_VERSION_MAGIC) (*e1)++;  if (**e2 == ERL_VERSION_MAGIC) (*e2)++;  if (cmp_array[**e1] < cmp_array[**e2]) return -1;  if (cmp_array[**e1] > cmp_array[**e2]) return 1;    if (IS_ERL_NUM(**e1))       return cmp_number(e1,e2);  if (cmp_array[**e1] == ERL_REF_CMP)      return cmp_refs(e1, e2);  return cmp_exe2(e1, e2);}int erl_compare_ext(unsigned char *e1, unsigned char *e2){  return compare_top_ext(&e1, &e2); } /* erl_compare_ext */#if defined(VXWORKS) && CPU == PPC860/* FIXME we have no floating point but don't we have emulation?! */int erl_fp_compare(unsigned *a, unsigned *b) {    /* Big endian mode of powerPC, IEEE floating point. */    unsigned a_split[4] = {a[0] >> 31,             /* Sign bit */                           (a[0] >> 20) & 0x7FFU,  /* Exponent */                           a[0] & 0xFFFFFU,        /* Mantissa MS bits */                           a[1]};                  /* Mantissa LS bits */    unsigned b_split[4] = {b[0] >> 31,                           (b[0] >> 20) & 0x7FFU,                           b[0] & 0xFFFFFU,                           b[1]};    int a_is_infinite, b_is_infinite;    int res;    /* Make -0 be +0 */    if (a_split[1] == 0 && a_split[2] == 0 && a_split[3] == 0)        a_split[0] = 0;    if (b_split[1] == 0 && b_split[2] == 0 && b_split[3] == 0)        b_split[0] = 0;    /* Check for infinity */    a_is_infinite = (a_split[1] == 0x7FFU && a_split[2] == 0 &&                      a_split[3] == 0);    b_is_infinite = (b_split[1] == 0x7FFU && b_split[2] == 0 &&                      b_split[3] == 0);    if (a_is_infinite && !b_is_infinite)        return (a_split[0]) ? -1 : 1;    if (b_is_infinite && !a_is_infinite)        return (b_split[0]) ? 1 : -1;    if (a_is_infinite && b_is_infinite)        return b[0] - a[0];     /* Check for indeterminate or nan, infinite is already handled,      so we only check the exponent. */    if((a_split[1] == 0x7FFU) || (b_split[1] == 0x7FFU))        return INT_MAX; /* Well, they are not equal anyway,                            abort() could be an alternative... */    if (a_split[0] && !b_split[0])        return -1;    if (b_split[0] && !a_split[0])        return 1;    /* Compare */    res = memcmp(a_split + 1, b_split + 1, 3 * sizeof(unsigned));    /* Make -1, 0 or 1 */    res = (!!res) * ((res < 0) ? -1 : 1);     /* Turn sign if negative values */    if (a_split[0]) /* Both are negative */        res = -1 * res;    return res;}static void join(unsigned d_split[4], unsigned *d){    d[0] = (d_split[0] << 31) |         /* Sign bit */	((d_split[1] & 0x7FFU) << 20) | /* Exponent */	(d_split[2] & 0xFFFFFU);        /* Mantissa MS bits */    d[1] = d_split[3];                  /* Mantissa LS bits */}static int blength(unsigned long l){    int i;    for(i = 0; l; ++i)	l >>= 1;    return i;}static void erl_long_to_fp(long l, unsigned *d) {    unsigned d_split[4];    unsigned x;    if (l < 0) {	d_split[0] = 1;	x = -l;    } else {	d_split[0] = 0;	x = l;    }    if (!l) {	memset(d_split,0,sizeof(d_split));    } else {	int len = blength(x);	x <<= (33 - len);	d_split[2] = (x >> 12);	d_split[3] = (x << 20);	d_split[1] = 1023 + len - 1;    }    join(d_split,d);}#endif/*  * Checks if a term is a "string": a flat list of byte-sized integers. * * Returns: 0 if the term is not a string, otherwise the length is returned. */static int is_string(ETERM* term){    int len = 0;    while (ERL_TYPE(term) == ERL_LIST) {	ETERM* head = HEAD(term);	if (!ERL_IS_INTEGER(head) || ((unsigned)head->uval.ival.i) > 255) {	    return 0;	}	len++;	term = TAIL(term);    }    if (ERL_IS_EMPTY_LIST(term)) {	return len;    }    return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?