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 + -
显示快捷键?