📄 utils.c
字号:
dsbufp->str = (char *) erts_alloc(ERTS_ALC_T_TMP_DSBUF, init_size); dsbufp->str[0] = '\0'; dsbufp->size = init_size; return dsbufp;}voiderts_destroy_tmp_dsbuf(erts_dsprintf_buf_t *dsbufp){ if (dsbufp->str) erts_free(ERTS_ALC_T_TMP_DSBUF, (void *) dsbufp->str); erts_free(ERTS_ALC_T_TMP_DSBUF, (void *) dsbufp);}/* eq and cmp are written as separate functions a eq is a little faster *//* * Test for equality of two terms. * Returns 0 if not equal, or a non-zero value otherwise. */inteq(Eterm a, Eterm b){ tailrecur: if (a == b) return 1; switch (primary_tag(a)) { case TAG_PRIMARY_BOXED: { Eterm hdr = *boxed_val(a); switch (hdr & _TAG_HEADER_MASK) { case ARITYVAL_SUBTAG: { Eterm* aa; Eterm* bb; Sint i; aa = tuple_val(a); if (!is_boxed(b) || *boxed_val(b) != *aa) return 0; bb = tuple_val(b); i = arityval(*aa); /* get the arity*/ while (i--) { Eterm atmp = *++aa; Eterm btmp = *++bb; if (!EQ(atmp, btmp)) return 0; } return 1; } case REFC_BINARY_SUBTAG: case HEAP_BINARY_SUBTAG: case SUB_BINARY_SUBTAG: { byte* a_ptr; byte* b_ptr; size_t a_size; size_t b_size; Uint a_bitsize; Uint b_bitsize; Uint a_bitoffs; Uint b_bitoffs; if (is_not_binary(b)) { return 0; } a_size = binary_size(a); b_size = binary_size(b); if (a_size != b_size) { return 0; } ERTS_GET_BINARY_BYTES(a, a_ptr, a_bitoffs, a_bitsize); ERTS_GET_BINARY_BYTES(b, b_ptr, b_bitoffs, b_bitsize); if ((a_bitsize | b_bitsize | a_bitoffs | b_bitoffs) == 0) { return sys_memcmp(a_ptr, b_ptr, a_size) == 0; } else if (a_bitsize == b_bitsize) { return erts_cmp_bits(a_ptr, a_bitoffs, b_ptr, b_bitoffs, (a_size << 3) + a_bitsize) == 0; } else { return 0; } } case EXPORT_SUBTAG: { Export* a_exp; Export* b_exp; if (is_not_export(b)) { return 0; } a_exp = (Export *) (export_val(a))[1]; b_exp = (Export *) (export_val(b))[1]; return a_exp == b_exp; } case FUN_SUBTAG: { ErlFunThing* f1; ErlFunThing* f2; int num_free; int i; if (is_not_fun(b)) return 0; f1 = (ErlFunThing *) fun_val(a); f2 = (ErlFunThing *) fun_val(b); if (f1->fe->module != f2->fe->module || f1->fe->old_index != f2->fe->old_index || f1->fe->old_uniq != f2->fe->old_uniq || f1->num_free != f2->num_free) { return 0; } num_free = f1->num_free; for (i = 0; i < num_free; i++) { if (!EQ(f1->env[i], f2->env[i])) { return 0; } } return 1; } case EXTERNAL_PID_SUBTAG: case EXTERNAL_PORT_SUBTAG: { ExternalThing *ap; ExternalThing *bp; if(is_not_external(b)) return 0; ap = external_thing_ptr(a); bp = external_thing_ptr(b); if(ap->header != bp->header) return 0; if(ap->node != bp->node) return 0; ASSERT(1 == external_data_words(a)); ASSERT(1 == external_data_words(b)); if(ap->data[0] != bp->data[0]) return 0; return 1; } case EXTERNAL_REF_SUBTAG: { /* * Observe! * When comparing refs we need to compare ref numbers * (32-bit words) *not* ref data words. */ Uint32 *anum; Uint32 *bnum; Uint common_len; Uint alen; Uint blen; Uint i; if(is_not_external_ref(b)) return 0; if(external_node(a) != external_node(b)) return 0; anum = external_ref_numbers(a); bnum = external_ref_numbers(b); alen = external_ref_no_of_numbers(a); blen = external_ref_no_of_numbers(b); goto ref_common; case REF_SUBTAG: if (is_not_internal_ref(b)) return 0; alen = internal_ref_no_of_numbers(a); blen = internal_ref_no_of_numbers(b); anum = internal_ref_numbers(a); bnum = internal_ref_numbers(b); ref_common: ASSERT(alen > 0 && blen > 0); if (anum[0] != bnum[0]) return 0; if (alen == 3 && blen == 3) { /* Most refs are of length 3 */ if (anum[1] == bnum[1] && anum[2] == bnum[2]) return 1; return 0; } common_len = alen; if (blen < alen) common_len = blen; for (i = 1; i < common_len; i++) if (anum[i] != bnum[i]) return 0; if(alen != blen) { if (alen > blen) { for (i = common_len; i < alen; i++) if (anum[i] != 0) return 0; } else { for (i = common_len; i < blen; i++) if (bnum[i] != 0) return 0; } } return 1; } case POS_BIG_SUBTAG: case NEG_BIG_SUBTAG: { Eterm* aa; Eterm* bb; int i; if (is_not_big(b)) return 0; aa = big_val(a); /* get pointer to thing */ bb = big_val(b); if (*aa != *bb) return 0; i = BIG_ARITY(aa); while(i--) { if (*++aa != *++bb) return 0; } return 1; } case FLOAT_SUBTAG: { FloatDef af; FloatDef bf; if (is_not_float(b)) return 0; GET_DOUBLE(a, af); GET_DOUBLE(b, bf); return (af.fd == bf.fd) ? 1 : 0; } } break; } case TAG_PRIMARY_LIST: { Eterm atmp; Eterm btmp; if (is_not_list(b)) return 0; atmp = CAR(list_val(a)); btmp = CAR(list_val(b)); if (!EQ(atmp, btmp)) return 0; a = CDR(list_val(a)); b = CDR(list_val(b)); goto tailrecur; } } return 0;}/* * Lexically compare two strings of bytes (string s1 length l1 and s2 l2). * * s1 < s2 return -1 * s1 = s2 return 0 * s1 > s2 return +1 */static int cmpbytes(byte *s1, int l1, byte *s2, int l2){ int i; i = 0; while((i < l1) && (i < l2)) { if (s1[i] < s2[i]) return(-1); if (s1[i] > s2[i]) return(1); i++; } if (l1 < l2) return(-1); if (l1 > l2) return(1); return(0);}/* * Compare objects. * Returns 0 if equal, a negative value if a < b, or a positive number a > b. * * According to the Erlang Standard, types are orderered as follows: * numbers < (characters) < atoms < refs < funs < ports < pids < * tuples < [] < conses < binaries. * * Note that characters are currently not implemented. * */#define float_comp(x,y) (((x)<(y)) ? -1 : (((x)==(y)) ? 0 : 1))static int cmp_atoms(Eterm a, Eterm b){ Atom *aa = atom_tab(atom_val(a)); Atom *bb = atom_tab(atom_val(b)); int diff = aa->ord0 - bb->ord0; if (diff) return diff; return cmpbytes(aa->name+3, aa->len-3, bb->name+3, bb->len-3);}Sintcmp(Eterm a, Eterm b){ Eterm* aa; Eterm* bb; int i; Sint j; Eterm big_buf[2]; int a_tag; int b_tag; ErlNode *anode; ErlNode *bnode; Uint adata; Uint bdata; Uint alen; Uint blen; Uint32 *anum; Uint32 *bnum;#undef CMP_NODES#define CMP_NODES(AN, BN) \ do { \ if((AN) != (BN)) { \ if((AN)->sysname != (BN)->sysname) \ return cmp_atoms((AN)->sysname, (BN)->sysname); \ ASSERT((AN)->creation != (BN)->creation); \ return ((AN)->creation < (BN)->creation) ? -1 : 1; \ } \ } while (0) tailrecur: if (a == b) { /* Equal values or pointers. */ return 0; } /* deal with majority (?) cases by brute-force */ if (is_atom(a)) { if (is_atom(b)) return cmp_atoms(a, b); } else if (is_both_small(a, b)) { return signed_val(a) - signed_val(b); } /* * Take care of cases where the types are the same. */ a_tag = 42; /* Suppress warning */ switch (primary_tag(a)) { case TAG_PRIMARY_IMMED1: switch ((a & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_PORT >> _TAG_PRIMARY_SIZE): if (is_internal_port(b)) { bnode = erts_this_node; bdata = internal_port_data(b); } else if (is_external_port(b)) { bnode = external_port_node(b); bdata = external_port_data(b); } else { a_tag = PORT_DEF; goto mixed_types; } anode = erts_this_node; adata = internal_port_data(a); port_common: CMP_NODES(anode, bnode); if (adata != bdata) { return adata < bdata ? -1 : 1; } return 0; case (_TAG_IMMED1_PID >> _TAG_PRIMARY_SIZE): if (is_internal_pid(b)) { bnode = erts_this_node; bdata = internal_pid_data(b); } else if (is_external_pid(b)) { bnode = external_pid_node(b); bdata = external_pid_data(b); } else { a_tag = PID_DEF; goto mixed_types; } anode = erts_this_node; adata = internal_pid_data(a); pid_common: if (adata != bdata) { return adata < bdata ? -1 : 1; } CMP_NODES(anode, bnode); return 0; case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): a_tag = SMALL_DEF; goto mixed_types; case (_TAG_IMMED1_IMMED2 >> _TAG_PRIMARY_SIZE): { switch ((a & _TAG_IMMED2_MASK) >> _TAG_IMMED1_SIZE) { case (_TAG_IMMED2_ATOM >> _TAG_IMMED1_SIZE): a_tag = ATOM_DEF; goto mixed_types; case (_TAG_IMMED2_NIL >> _TAG_IMMED1_SIZE): a_tag = NIL_DEF; goto mixed_types; } } } case TAG_PRIMARY_LIST: if (is_not_list(b)) { a_tag = LIST_DEF; goto mixed_types; } aa = list_val(a); bb = list_val(b); while (1) { if ((j = cmp(*aa++, *bb++)) != 0) return j; if (*aa==*bb) return 0; if (is_not_list(*aa) || is_not_list(*bb)) { a = *aa; b = *bb; goto tailrecur; } aa = list_val(*aa); bb = list_val(*bb); } case TAG_PRIMARY_BOXED: { Eterm ahdr = *boxed_val(a); switch ((ahdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_HEADER_ARITYVAL >> _TAG_PRIMARY_SIZE): if (is_not_tuple(b)) { a_tag = TUPLE_DEF; goto mixed_types; } aa = tuple_val(a); bb = tuple_val(b); /* compare the arities */ i = arityval(ahdr); /* get the arity*/ if (i < arityval(*bb)) return(-1); if (i > arityval(*bb)) return(1); if (i == 0) { return 0; } while (--i) { a = *++aa; b = *++bb; if (a != b) { if (is_atom(a) && is_atom(b)) { if ((j = cmp_atoms(a, b)) != 0) { return j; } } else if (is_both_small(a, b)) { if ((j = signed_val(a)-signed_val(b)) != 0) { return j; } } else if ((j = cmp(a, b)) != 0) { return j; } } } a = *++aa; b = *++bb; goto tailrecur; case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): if (is_not_float(b)) { a_tag = FLOAT_DEF; goto mixed_types; } else { FloatDef af; FloatDef bf; GET_DOUBLE(a, af); GET_DOUBLE(b, bf); return float_comp(af.fd, bf.fd); } case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): if (is_not_big(b)) { a_tag = BIG_DEF; goto mixed_types; } return big_comp(a, b); case (_TAG_HEADER_EXPORT >> _TAG_PRIMARY_SIZE): if (is_not_export(b)) { a_tag = EXPORT_DEF; goto mixed_types; } else { Export* a_exp = (Export *) (export_val(a))[1]; Export* b_exp = (Export *) (export_val(b))[1]; if ((j = cmp_atoms(a_exp->code[0], b_exp->code[0])) != 0) { return j; } if ((j = cmp_atoms(a_exp->code[1], b_exp->code[1])) != 0) { return j; } return (Sint) a_exp->code[2] - (Sint) b_exp->code[2]; } break; case (_TAG_HEADER_FUN >> _TAG_PRIMARY_SIZE): if (is_not_fun(b)) { a_tag = FUN_DEF; goto mixed_types; } else { ErlFunThing* f1 = (ErlFunThing *) fun_val(a); ErlFunThing* f2 = (ErlFunThing *) fun_val(b); int num_free; Sint diff; diff = cmpbytes(atom_tab(atom_val(f1->fe->module))->name, atom_tab(atom_val(f1->fe->module))->len, atom_tab(atom_val(f2->fe->module))->name, atom_tab(atom_val(f2->fe->module))->len); if (diff != 0) { return diff; } diff = f1->fe->old_index - f2->fe->old_index; if (diff != 0) { return diff; } diff = f1->fe->old_uniq - f2->fe->old_uniq; if (diff != 0) { return diff; } diff = f1->num_free - f2->num_free; if (diff != 0) { return diff; } num_free = f1->num_free; for (i = 0; i < num_free; i++) { if ((diff = cmp(f1->env[i], f2->env[i])) != 0) { return diff; } } return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -