📄 erl_bits.c
字号:
if (num_bits == 64) { t[7] = b >> 24; t[6] = b >> 16; t[5] = b >> 8; t[4] = b; }#endif } else { byte* t = erts_current_bin+BYTE_OFFSET(erts_bin_offset) + NBYTES(num_bits);#ifdef WORDS_BIGENDIAN t[-1] = a >> 24; t[-2] = a >> 16; t[-3] = a >> 8; t[-4] = a; if (num_bits == 64) { t[-5] = b >> 24; t[-6] = b >> 16; t[-7] = b >> 8; t[-8] = b; }#else t[-1] = a; t[-2] = a >> 8; t[-3] = a >> 16; t[-4] = a >> 24; if (num_bits == 64) { t[-5] = b; t[-6] = b >> 8; t[-7] = b >> 16; t[-8] = b >> 24; }#endif } } else { byte *bptr; double f64; float f32; if (num_bits == 64) { if (is_float(arg)) { bptr = (byte *) (float_val(arg) + 1); } else if (is_small(arg)) { f64 = (double) signed_val(arg); bptr = (byte *) &f64; } else if (is_big(arg)) { if (big_to_double(arg, &f64) < 0) { return 0; } bptr = (byte *) &f64; } else { return 0; } } else if (num_bits == 32) { if (is_float(arg)) { FloatDef f; GET_DOUBLE(arg, f); ERTS_FP_CHECK_INIT(c_p); f32 = f.fd; ERTS_FP_ERROR(c_p,f32,;); bptr = (byte *) &f32; } else if (is_small(arg)) { f32 = (float) signed_val(arg); bptr = (byte *) &f32; } else if (is_big(arg)) { if (big_to_double(arg, &f64) < 0) { return 0; } ERTS_FP_CHECK_INIT(c_p); f32 = (float) f64; ERTS_FP_ERROR(c_p,f32,;); bptr = (byte *) &f32; } else { return 0; } } else { return 0; } if (BIT_IS_MACHINE_ENDIAN(flags)) { erts_copy_bits(bptr, 0, 1, erts_current_bin, erts_bin_offset, 1, num_bits); } else { erts_copy_bits(bptr+NBYTES(num_bits)-1, 0, -1, erts_current_bin, erts_bin_offset, 1, num_bits); } } erts_bin_offset += num_bits; return 1;}void erts_new_bs_put_string(ERL_BITS_PROTO_2(byte* iptr, Uint num_bytes)){ if (BIT_OFFSET(erts_bin_offset) != 0) { erts_copy_bits(iptr, 0, 1, erts_current_bin, erts_bin_offset, 1, num_bytes*8); } else { sys_memcpy(erts_current_bin+BYTE_OFFSET(erts_bin_offset), iptr, num_bytes); } erts_bin_offset += num_bytes*8;}Etermerts_bs_final2(Process* p, Eterm bin){ ErlSubBin* sb; ERL_BITS_DEFINE_STATEP(p); if ((erts_bin_offset & 7) == 0) {return bin;} sb = (ErlSubBin *) HeapOnlyAlloc(p, ERL_SUB_BIN_SIZE); sb->thing_word = HEADER_SUB_BIN; sb->size = (erts_bin_offset - (erts_bin_offset & 7))/8; sb->bitsize = erts_bin_offset & 7; sb->offs = 0; sb->bitoffs = 0; sb->orig = bin; return make_binary(sb);}#if !defined(HEAP_FRAG_ELIM_TEST)/* * Old instructions for building binaries. */static voidERTS_INLINE need_bin_buf(ERL_BITS_PROTO_1(int need)){ if (erts_bin_buf_len < need) {#ifdef ERTS_SMP erts_smp_atomic_add(&bits_bufs_size, need - erts_bin_buf_len);#endif erts_bin_buf_len = need; erts_bin_buf = erts_realloc(ERTS_ALC_T_BITS_BUF, erts_bin_buf, erts_bin_buf_len); }}voiderts_bs_init(ERL_BITS_PROTO_0){ erts_bin_offset = 0;}Etermerts_bs_final(Process* p){ ERL_BITS_DEFINE_STATEP(p); if (erts_bin_offset % 8 != 0) { return THE_NON_VALUE; } return new_binary_arith(p, erts_bin_buf, erts_bin_offset / 8);}interts_bs_put_integer(ERL_BITS_PROTO_3(Eterm arg, Uint num_bits, unsigned flags)){ unsigned bin_offset = erts_bin_offset; if (BIT_OFFSET(bin_offset) == 0) { need_bin_buf(ERL_BITS_ARGS_1(NBYTES(num_bits+bin_offset))); if (fmt_int(erts_bin_buf+BYTE_OFFSET(bin_offset), NBYTES(num_bits), arg, num_bits, flags) < 0) { return 0; } } else { byte *iptr; need_byte_buf(ERL_BITS_ARGS_1(NBYTES(num_bits))); iptr = byte_buf; if (fmt_int(iptr, NBYTES(num_bits), arg, num_bits, flags) < 0) { return 0; } need_bin_buf(ERL_BITS_ARGS_1(NBYTES(num_bits+bin_offset))); erts_copy_bits(iptr, 0, 1, erts_bin_buf, bin_offset, 1, num_bits); } erts_bin_offset = bin_offset + num_bits; return 1;}interts_bs_put_binary(ERL_BITS_PROTO_2(Eterm arg, Uint num_bits)){ byte *bptr; Uint bitoffs; Uint bitsize; if (!is_binary(arg)) { return 0; } ERTS_GET_BINARY_BYTES(arg, bptr, bitoffs, bitsize); if (num_bits > 8*binary_size(arg)+bitsize) { return 0; } need_bin_buf(ERL_BITS_ARGS_1(NBYTES(num_bits + erts_bin_offset))); if ((BIT_OFFSET(erts_bin_offset) == 0) & (bitoffs == 0) & (BIT_OFFSET(num_bits) == 0)) { sys_memcpy(erts_bin_buf+BYTE_OFFSET(erts_bin_offset), bptr, NBYTES(num_bits)); } else { erts_copy_bits(bptr, bitoffs, 1, erts_bin_buf, erts_bin_offset, 1, num_bits); } erts_bin_offset += num_bits; return 1;}interts_bs_put_binary_all(ERL_BITS_PROTO_1(Eterm arg)){ byte *bptr; unsigned n; Uint bitoffs; Uint bitsize; if (!is_binary(arg)) { return 0; } ERTS_GET_BINARY_BYTES(arg, bptr, bitoffs, bitsize); n = 8*binary_size(arg)+bitsize; need_bin_buf(ERL_BITS_ARGS_1(NBYTES(n + erts_bin_offset))); if ((BIT_OFFSET(erts_bin_offset) == 0) & (bitoffs == 0) & (bitsize == 0)) { sys_memcpy(erts_bin_buf+BYTE_OFFSET(erts_bin_offset), bptr, NBYTES(n)); } else { erts_copy_bits(bptr, bitoffs, 1, erts_bin_buf, erts_bin_offset, 1, n); } erts_bin_offset += n; return 1;}interts_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags){ byte *bptr; double f64; float f32; ERL_BITS_DEFINE_STATEP(c_p); if (num_bits == 64) { if (is_float(arg)) { bptr = (byte *) (float_val(arg) + 1); } else if (is_small(arg)) { f64 = (double) signed_val(arg); bptr = (byte *) &f64; } else if (is_big(arg)) { if (big_to_double(arg, &f64) < 0) { return 0; } bptr = (byte *) &f64; } else { return 0; } } else if (num_bits == 32) { if (is_float(arg)) { FloatDef f; GET_DOUBLE(arg, f); ERTS_FP_CHECK_INIT(c_p); f32 = f.fd; ERTS_FP_ERROR(c_p,f32,;); bptr = (byte *) &f32; } else if (is_small(arg)) { f32 = (float) signed_val(arg); bptr = (byte *) &f32; } else if (is_big(arg)) { if (big_to_double(arg, &f64) < 0) { return 0; } ERTS_FP_CHECK_INIT(c_p); f32 = (float) f64; ERTS_FP_ERROR(c_p,f32,;); bptr = (byte *) &f32; } else { return 0; } } else { return 0; } need_bin_buf(ERL_BITS_ARGS_1(NBYTES(num_bits + erts_bin_offset))); if (BIT_OFFSET(erts_bin_offset) == 0) { if (BIT_IS_MACHINE_ENDIAN(flags)) { byte* t = erts_bin_buf+BYTE_OFFSET(erts_bin_offset); t[0] = bptr[0]; t[1] = bptr[1]; t[2] = bptr[2]; t[3] = bptr[3]; if (num_bits == 64) { t[4] = bptr[4]; t[5] = bptr[5]; t[6] = bptr[6]; t[7] = bptr[7]; } } else { byte* t = erts_bin_buf+BYTE_OFFSET(erts_bin_offset) + NBYTES(num_bits); t[-1] = bptr[0]; t[-2] = bptr[1]; t[-3] = bptr[2]; t[-4] = bptr[3]; if (num_bits == 64) { t[-5] = bptr[4]; t[-6] = bptr[5]; t[-7] = bptr[6]; t[-8] = bptr[7]; } } } else { if (BIT_IS_MACHINE_ENDIAN(flags)) { erts_copy_bits(bptr, 0, 1, erts_bin_buf, erts_bin_offset, 1, num_bits); } else { erts_copy_bits(bptr+NBYTES(num_bits)-1, 0, -1, erts_bin_buf, erts_bin_offset, 1, num_bits); } } erts_bin_offset += num_bits; return 1;}void erts_bs_put_string(ERL_BITS_PROTO_2(byte* iptr, Uint num_bytes)){ need_bin_buf(ERL_BITS_ARGS_1(num_bytes + NBYTES(erts_bin_offset))); if (BIT_OFFSET(erts_bin_offset) != 0) { erts_copy_bits(iptr, 0, 1, erts_bin_buf, erts_bin_offset, 1, num_bytes*8); } else { sys_memcpy(erts_bin_buf+BYTE_OFFSET(erts_bin_offset), iptr, num_bytes); } erts_bin_offset += num_bytes*8;}#endifstatic byteget_bit(byte b, size_t offs) { return (b >> (7-offs)) & 1;}interts_cmp_bits(byte* a_ptr, size_t a_offs, byte* b_ptr, size_t b_offs, size_t size) { byte a; byte b; byte a_bit; byte b_bit; Uint lshift; Uint rshift; int cmp; if (((a_offs | b_offs | size) & 7) == 0) { int byte_size = size >> 3; return sys_memcmp(a_ptr, b_ptr, byte_size); } /* Compare bit by bit until a_ptr is aligned on byte boundary */ a = *a_ptr++; b = *b_ptr++; while (size > 0) { a_bit = get_bit(a, a_offs); b_bit = get_bit(b, b_offs); if ((cmp = (a_bit-b_bit)) != 0) { return cmp; } size--; b_offs++; if (b_offs == 8) { b_offs = 0; b = *b_ptr++; } a_offs++; if (a_offs == 8) { a_offs = 0; a = *a_ptr++; break; } } /* Compare byte by byte as long as at least 8 bits remain */ lshift = b_offs; rshift = 8 - lshift; while (size >= 8) { byte b_cmp = (b << lshift); b = *b_ptr++; b_cmp |= b >> rshift; if ((cmp = (a - b_cmp)) != 0) { return cmp; } a = *a_ptr++; size -= 8; } /* Compare the remaining bits bit by bit */ while (size > 0) { a_bit = get_bit(a, a_offs); b_bit = get_bit(b, b_offs); if ((cmp = (a_bit-b_bit)) != 0) { return cmp; } a_offs++; if (a_offs == 8) { a_offs = 0; a = *a_ptr++; } b_offs++; if (b_offs == 8) { b_offs = 0; b = *b_ptr++; } size--; } return 0;}/* * The basic bit copy operation. Copies n bits from the source buffer to * the destination buffer. Depending on the directions, it can reverse the * copied bits. */void erts_copy_bits(byte* src, /* Base pointer to source. */ size_t soffs, /* Bit offset for source relative to src. */ int sdir, /* Direction: 1 (forward) or -1 (backward). */ byte* dst, /* Base pointer to destination. */ size_t doffs, /* Bit offset for destination relative to dst. */ int ddir, /* Direction: 1 (forward) or -1 (backward). */ size_t n) /* Number of bits to copy. */{ Uint lmask; Uint rmask; Uint count; Uint deoffs; if (n == 0) { return; } src += sdir*BYTE_OFFSET(soffs); dst += ddir*BYTE_OFFSET(doffs); soffs = BIT_OFFSET(soffs); doffs = BIT_OFFSET(doffs); deoffs = BIT_OFFSET(doffs+n); lmask = (doffs) ? MAKE_MASK(8-doffs) : 0; rmask = (deoffs) ? (MAKE_MASK(deoffs)<<(8-deoffs)) : 0; /* * Take care of the case that all bits are in the same byte. */ if (doffs+n < 8) { /* All bits are in the same byte */ lmask = (lmask & rmask) ? (lmask & rmask) : (lmask | rmask); if (soffs == doffs) { *dst = MASK_BITS(*src,*dst,lmask); } else if (soffs > doffs) { Uint bits = (*src << (soffs-doffs)); if (soffs+n > 8) { src += sdir; bits |= (*src >> (8-(soffs-doffs))); } *dst = MASK_BITS(bits,*dst,lmask); } else { *dst = MASK_BITS((*src >> (doffs-soffs)),*dst,lmask); } return; /* We are done! */ } /* * At this point, we know that the bits are in 2 or more bytes. */ count = ((lmask) ? (n - (8 - doffs)) : n) >> 3; if (soffs == doffs) { /* * The bits are aligned in the same way. We can just copy the bytes * (except for the first and last bytes). Note that the directions * might be different, so we can't just use memcpy(). */ if (lmask) { *dst = MASK_BITS(*src, *dst, lmask); dst += ddir; src += sdir; } while (count--) { *dst = *src; dst += ddir; src += sdir; } if (rmask) { *dst = MASK_BITS(*src,*dst,rmask); } } else { Uint bits; Uint bits1; Uint rshift; Uint lshift; /* * The tricky case. The bits must be shifted into position. */ if (soffs > doffs) { lshift = (soffs - doffs); rshift = 8 - lshift; bits = *src; if (soffs + n > 8) { src += sdir; } } else { rshift = (doffs - soffs); lshift = 8 - rshift; bits = 0; } if (lmask) { bits1 = bits << lshift; bits = *src; src += sdir; bits1 |= (bits >> rshift); *dst = MASK_BITS(bits1,*dst,lmask); dst += ddir; } while (count--) { bits1 = bits << lshift; bits = *src; src += sdir; *dst = bits1 | (bits >> rshift); dst += ddir; } if (rmask) { bits1 = bits << lshift; if ((rmask << rshift) & 0xff) { bits = *src; bits1 |= (bits >> rshift); } *dst = MASK_BITS(bits1,*dst,rmask); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -