📄 utils.c
字号:
} case (_TAG_HEADER_EXTERNAL_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 = EXTERNAL_PID_DEF; goto mixed_types; } anode = external_pid_node(a); adata = external_pid_data(a); goto pid_common; case (_TAG_HEADER_EXTERNAL_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 = EXTERNAL_PORT_DEF; goto mixed_types; } anode = external_port_node(a); adata = external_port_data(a); goto port_common; case (_TAG_HEADER_REF >> _TAG_PRIMARY_SIZE): /* * Note! When comparing refs we need to compare ref numbers * (32-bit words), *not* ref data words. */ if (is_internal_ref(b)) { bnode = erts_this_node; bnum = internal_ref_numbers(b); blen = internal_ref_no_of_numbers(b); } else if(is_external_ref(b)) { bnode = external_ref_node(b); bnum = external_ref_numbers(b); blen = external_ref_no_of_numbers(b); } else { a_tag = REF_DEF; goto mixed_types; } anode = erts_this_node; anum = internal_ref_numbers(a); alen = internal_ref_no_of_numbers(a); ref_common: CMP_NODES(anode, bnode); ASSERT(alen > 0 && blen > 0); if (alen != blen) { if (alen > blen) { do { if (anum[alen - 1] != 0) return 1; alen--; } while (alen > blen); } else { do { if (bnum[blen - 1] != 0) return -1; blen--; } while (alen < blen); } } ASSERT(alen == blen); for (i = (Sint) alen - 1; i >= 0; i--) if (anum[i] != bnum[i]) return anum[i] < bnum[i] ? -1 : 1; return 0; case (_TAG_HEADER_EXTERNAL_REF >> _TAG_PRIMARY_SIZE): if (is_internal_ref(b)) { bnode = erts_this_node; bnum = internal_ref_numbers(b); blen = internal_ref_no_of_numbers(b); } else if (is_external_ref(b)) { bnode = external_ref_node(b); bnum = external_ref_numbers(b); blen = external_ref_no_of_numbers(b); } else { a_tag = EXTERNAL_REF_DEF; goto mixed_types; } anode = external_ref_node(a); anum = external_ref_numbers(a); alen = external_ref_no_of_numbers(a); goto ref_common; default: /* Must be a binary */ ASSERT(is_binary(a)); if (is_not_binary(b)) { a_tag = BINARY_DEF; goto mixed_types; } else { Uint a_size = binary_size(a); Uint b_size = binary_size(b); Uint a_bitsize; Uint b_bitsize; Uint a_bitoffs; Uint b_bitoffs; Uint min_size; int cmp; byte* a_ptr; byte* b_ptr; 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) { min_size = (a_size < b_size) ? a_size : b_size; if ((cmp = sys_memcmp(a_ptr, b_ptr, min_size)) != 0) { return cmp; } else { return a_size - b_size; } } else { a_size = (a_size << 3) + a_bitsize; b_size = (b_size << 3) + b_bitsize; min_size = (a_size < b_size) ? a_size : b_size; if ((cmp = erts_cmp_bits(a_ptr,a_bitoffs, b_ptr,b_bitoffs,min_size)) != 0) { return cmp; } else { return a_size - b_size; } } } } } } /* * Take care of the case that the tags are different. */ mixed_types: b_tag = tag_val_def(b); { FloatDef f1, f2; Eterm big; switch(_NUMBER_CODE(a_tag, b_tag)) { case SMALL_BIG: big = small_to_big(signed_val(a), big_buf); return big_comp(big, b); case SMALL_FLOAT: f1.fd = signed_val(a); GET_DOUBLE(b, f2); return float_comp(f1.fd, f2.fd); case BIG_SMALL: big = small_to_big(signed_val(b), big_buf); return big_comp(a, big); case BIG_FLOAT: if (big_to_double(a, &f1.fd) < 0) { return big_sign(a) ? -1 : 1; } GET_DOUBLE(b, f2); return float_comp(f1.fd, f2.fd); case FLOAT_SMALL: GET_DOUBLE(a, f1); f2.fd = signed_val(b); return float_comp(f1.fd, f2.fd); case FLOAT_BIG: if (big_to_double(b, &f2.fd) < 0) { return big_sign(b) ? 1 : -1; } GET_DOUBLE(a, f1); return float_comp(f1.fd, f2.fd); default: return b_tag - a_tag; } }#undef CMP_NODES}voiderts_cleanup_externals(ExternalThing *etp){ ExternalThing *tetp; tetp = etp; while(tetp) { erts_deref_node_entry(tetp->node); tetp = tetp->next; }}Etermstore_external_or_ref_(Uint **hpp, ExternalThing **etpp, Eterm ns){ Uint i; Uint size; Uint *from_hp; Uint *to_hp = *hpp; ASSERT(is_external(ns) || is_internal_ref(ns)); if(is_external(ns)) { from_hp = external_val(ns); size = thing_arityval(*from_hp) + 1; *hpp += size; for(i = 0; i < size; i++) to_hp[i] = from_hp[i]; erts_refc_inc(&((ExternalThing *) to_hp)->node->refc, 2); ((ExternalThing *) to_hp)->next = *etpp; *etpp = (ExternalThing *) to_hp; return make_external(to_hp); } /* Internal ref */ from_hp = internal_ref_val(ns); size = thing_arityval(*from_hp) + 1; *hpp += size; for(i = 0; i < size; i++) to_hp[i] = from_hp[i]; return make_internal_ref(to_hp);}Etermstore_external_or_ref_in_proc_(Process *proc, Eterm ns){ Uint sz; Uint *hp; ASSERT(is_external(ns) || is_internal_ref(ns)); sz = NC_HEAP_SIZE(ns); ASSERT(sz > 0); hp = HAlloc(proc, sz); return store_external_or_ref_(&hp, &MSO(proc).externals, ns);}/* * member(X,Y) * returns 0 if X is a member of list Y * returns 1 if X is not a member of list Y * returns 2 if Y is not a list or is a badly formed list */intmember(Eterm x, Eterm y){ Eterm* z; if (is_nil(y)) return(1); /* empty list */ if (is_not_list(y)) return(2); /* bad argument */ z = list_val(y); for (;;) { if (eq(*z, x)) return(0); if (is_nil(*(z + 1))) return(1); /* end of list */ if (is_not_list(*(z + 1))) return(2); /* badly formed list */ z = list_val(*(z + 1)); }}void bin_write(int to, void *to_arg, byte* buf, int sz){ int i; for (i=0;i<sz;i++) { if (IS_DIGIT(buf[i])) erts_print(to, to_arg, "%d,", buf[i]); else if (IS_PRINT(buf[i])) { erts_print(to, to_arg, "%c,", buf[i]); } else erts_print(to, to_arg, "%d,", buf[i]); } erts_putc(to, to_arg, '\n');}/* Fill buf with the contents of bytelist list return number of chars in list or -1 for error */intintlist_to_buf(Eterm list, char *buf, int len){ Eterm* listptr; int sz = 0; if (is_nil(list)) return 0; if (is_not_list(list)) return -1; listptr = list_val(list); while (sz < len) { if (!is_byte(*listptr)) return -1; buf[sz++] = unsigned_val(*listptr); if (is_nil(*(listptr + 1))) return(sz); if (is_not_list(*(listptr + 1))) return -1; listptr = list_val(*(listptr + 1)); } return -1; /* not enough space */}/*** Convert an integer to a byte list** return pointer to converted stuff (need not to be at start of buf!)*/char* Sint_to_buf(Sint n, struct Sint_buf *buf){ char* p = &buf->s[sizeof(buf->s)-1]; int sign = 0; *p-- = '\0'; /* null terminate */ if (n == 0) *p-- = '0'; else if (n < 0) { sign = 1; n = -n; } while (n != 0) { *p-- = (n % 10) + '0'; n /= 10; } if (sign) *p-- = '-'; return p+1;}/* Build a list of integers in some safe memory area** Memory must be pre allocated prio call 2*len in size** hp is a pointer to the "heap" pointer on return** this pointer is updated to point after the list*/Etermbuf_to_intlist(Eterm** hpp, char *buf, int len, Eterm tail){ Eterm* hp = *hpp; buf += (len-1); while(len > 0) { tail = CONS(hp, make_small((byte)*buf), tail); hp += 2; buf--; len--; } *hpp = hp; return tail;}/*** Write io list in to a buffer.**** An iolist is defined as:**** iohead ::= Binary** | Byte (i.e integer in range [0..255]** | iolist** ;**** iotail ::= []** | Binary (added by tony)** | iolist** ;**** iolist ::= []** | Binary** | [ iohead | iotail]** ;** ** Return remaining bytes in buffer on success** -1 on overflow** -2 on type error (including that result would not be a whole number of bytes)*/int io_list_to_buf(Eterm obj, char* buf, int len){ Eterm* objp; DECLARE_ESTACK(s); goto L_again; while (!ESTACK_ISEMPTY(s)) { obj = ESTACK_POP(s); L_again: if (is_list(obj)) { L_iter_list: objp = list_val(obj); obj = CAR(objp); if (is_byte(obj)) { if (len == 0) { goto L_overflow; } *buf++ = unsigned_val(obj); len--; } else if (is_binary(obj)) { byte* bptr; size_t size = binary_size(obj); Uint bitsize; Uint bitoffs; Uint num_bits; if (len < size) { goto L_overflow; } ERTS_GET_BINARY_BYTES(obj, bptr, bitoffs, bitsize); if (bitsize != 0) { goto L_type_error; } num_bits = 8*size; copy_binary_to_buffer(buf, 0, bptr, bitoffs, num_bits); buf += size; len -= size; } else if (is_list(obj)) { ESTACK_PUSH(s, CDR(objp)); goto L_iter_list; /* on head */ } else if (is_not_nil(obj)) { goto L_type_error; } obj = CDR(objp); if (is_list(obj)) { goto L_iter_list; /* on tail */ } else if (is_binary(obj)) { byte* bptr; size_t size = binary_size(obj); Uint bitsize; Uint bitoffs; Uint num_bits; if (len < size) { goto L_overflow; } ERTS_GET_BINARY_BYTES(obj, bptr, bitoffs, bitsize); if (bitsize != 0) { goto L_type_error; } num_bits = 8*size; copy_binary_to_buffer(buf, 0, bptr, bitoffs, num_bits); buf += size; len -= size; } else if (is_not_nil(obj)) { goto L_type_error; } } else if (is_binary(obj)) { byte* bptr; size_t size = binary_size(obj); Uint bitsize; Uint bitoffs; Uint num_bits; if (len < size) { goto L_overflow; } ERTS_GET_BINARY_BYTES(obj, bptr, bitoffs, bitsize); if (bitsize != 0) { goto L_type_error; } num_bits = 8*size; copy_binary_to_buffer(buf, 0, bptr, bitoffs, num_bits); buf += size; len -= size; } else if (is_not_nil(obj)) { goto L_type_error; } } DESTROY_ESTACK(s); return len; L_type_error: DESTROY_ESTACK(s); return -2; L_overflow: DESTROY_ESTACK(s); return -1;}int io_list_len(Eterm obj){ Eterm* objp; Sint len = 0; DECLARE_ESTACK(s); goto L_again; while (!ESTACK_ISEMPTY(s)) { obj = ESTACK_POP(s); L_again: if (is_list(obj)) { L_iter_list: objp = list_val(obj); /* Head */ obj = CAR(objp); if (is_byte(obj)) { len++; } else if (is_binary(obj) && binary_bitsize(obj) == 0) { len += binary_size(obj); } else if (is_list(obj)) { ESTACK_PUSH(s, CDR(objp)); goto L_iter_list; /* on head */ } else if (is_not_nil(obj)) { goto L_type_error; } /* Tail */ obj = CDR(objp); if (is_list(obj)) goto L_iter_list; /* on tail */ else if (is_binary(obj) && binary_bitsize(obj) == 0) { len += binary_size(obj); } else if (is_not_nil(obj)) { goto L_type_error; } } else if (is_binary(obj) && binary_bitsize(obj) == 0) { /* Tail was binary */ len += binary_size(obj); } else if (is_not_nil(obj)) { goto L_type_error; } } DESTROY_ESTACK(s); return len; L_type_error: DESTROY_ESTACK(s); return -1;}/* return 0 if item is not a non-empty flat list of bytes */intis_string(Eterm list){ int len = 0; while(is_list(list)) { Eterm* consp = list_val(list); Eterm hd = CAR(consp); if (!is_byte(hd)) return 0; len++; list = CDR(con
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -