📄 erl_bits.c
字号:
byte* ptr = LSB; byte c = 1; /* sign extend MSB */ *MSB |= ~MAKE_MASK(bits); /* two's complement */ while (ptr <= MSB) { byte pd = ~(*ptr); byte d = pd + c; c = (d < pd); *ptr++ = d; } sgn = 1; } /* normalize */ while ((*MSB == 0) && (MSB > LSB)) { MSB--; bytes--; } /* check for guaranteed small num */ switch (bytes) { case 1: v32 = LSB[0]; goto big_small; case 2: v32 = LSB[0] + (LSB[1]<<8); goto big_small; case 3: v32 = LSB[0] + (LSB[1]<<8) + (LSB[2]<<16); goto big_small;#if !defined(ARCH_64) case 4: v32 = (LSB[0] + (LSB[1]<<8) + (LSB[2]<<16) + (LSB[3]<<24)); if (!IS_USMALL(sgn, v32)) { goto make_big; }#else case 4: ReadToVariable(v32, LSB, 4); goto big_small; case 5: ReadToVariable(v32, LSB, 5); goto big_small; case 6: ReadToVariable(v32, LSB, 6); goto big_small; case 7: ReadToVariable(v32, LSB, 7); goto big_small; case 8: ReadToVariable(v32, LSB, 8); if (!IS_USMALL(sgn, v32)) { goto make_big; }#endif big_small: /* v32 loaded with value which fits in fixnum */ if (sgn) { res = make_small(-((Sint)v32)); } else { res = make_small(v32); } break; make_big: hp = HeapOnlyAlloc(p, BIG_UINT_HEAP_SIZE); if (sgn) { hp[0] = make_neg_bignum_header(1); } else { hp[0] = make_pos_bignum_header(1); } BIG_DIGIT(hp,0) = DLOW(v32); BIG_DIGIT(hp,1) = DHIGH(v32); res = make_big(hp); break; default: words_needed = 1+WSIZE(bytes); hp = HeapOnlyAlloc(p, words_needed); hp_end = hp + words_needed; res = bytes_to_big(LSB, bytes, sgn, hp); if (is_small(res)) { p->htop = hp; } else if ((actual = bignum_header_arity(*hp)+1) < words_needed) { p->htop = hp + actual; } break; } if (LSB != bigbuf) { erts_free(ERTS_ALC_T_TMP, (void *) LSB); } return res;}Etermerts_bs_get_binary_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb){ ErlSubBin* sb; size_t num_bytes; /* Number of bytes in binary. */ if (num_bits == 0) { /* Empty binary. */ return new_binary(p, NULL, 0); } if (mb->size - mb->offset < num_bits) { /* Asked for too many bits. */ return THE_NON_VALUE; } /* * From now on, we can't fail. */ num_bytes = NBYTES(num_bits); sb = (ErlSubBin *) HeapOnlyAlloc(p, ERL_SUB_BIN_SIZE); sb->thing_word = HEADER_SUB_BIN; sb->orig = mb->orig; sb->size = BYTE_OFFSET(num_bits); sb->bitsize = BIT_OFFSET(num_bits); sb->offs = BYTE_OFFSET(mb->offset); sb->bitoffs = BIT_OFFSET(mb->offset); mb->offset += num_bits; return make_binary(sb);}Etermerts_bs_get_float_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb){ Eterm* hp; float f32; double f64; byte* fptr; FloatDef f; if (num_bits == 0) { f.fd = 0.0; hp = HeapOnlyAlloc(p, FLOAT_SIZE_OBJECT); PUT_DOUBLE(f, hp); return make_float(hp); } if (mb->size - mb->offset < num_bits) { /* Asked for too many bits. */ return THE_NON_VALUE; } if (num_bits == 32) { fptr = (byte *) &f32; } else if (num_bits == 64) { fptr = (byte *) &f64; } else { return THE_NON_VALUE; } if (BIT_IS_MACHINE_ENDIAN(flags)) { erts_copy_bits(mb->base, mb->offset, 1, fptr, 0, 1, num_bits); } else { erts_copy_bits(mb->base, mb->offset, 1, fptr + NBYTES(num_bits) - 1, 0, -1, num_bits); } ERTS_FP_CHECK_INIT(p); if (num_bits == 32) { ERTS_FP_ERROR_THOROUGH(p, f32, return THE_NON_VALUE); f.fd = f32; } else { ERTS_FP_ERROR_THOROUGH(p, f64, return THE_NON_VALUE); f.fd = f64; } mb->offset += num_bits; hp = HeapOnlyAlloc(p, FLOAT_SIZE_OBJECT); PUT_DOUBLE(f, hp); return make_float(hp);}Etermerts_bs_get_binary_all_2(Process *p, ErlBinMatchBuffer* mb){ ErlSubBin* sb; Uint size; size = mb->size-mb->offset; sb = (ErlSubBin *) HeapOnlyAlloc(p, ERL_SUB_BIN_SIZE); sb->thing_word = HEADER_SUB_BIN; sb->size = BYTE_OFFSET(size); sb->bitsize = BIT_OFFSET(size); sb->offs = BYTE_OFFSET(mb->offset); sb->bitoffs = BIT_OFFSET(mb->offset); sb->orig = mb->orig; mb->offset = mb->size; return make_binary(sb);}voiderts_bs_save_2(int index, ErlBinMatchState* ms){ ms->save_offset[index] = (ms->mb).offset;}void erts_bs_restore_2(int index, ErlBinMatchState* ms){ (ms->mb).offset = ms->save_offset[index];}/**************************************************************** *** *** Building binaries *** ****************************************************************//* COPY_VAL: * copy sz byte from val to dst buffer, * dst, val are updated!!! */#define COPY_VAL(dst,ddir,val,sz) do { \ Uint __sz = (sz); \ while(__sz) { \ switch(__sz) { \ default: \ case 4: *dst = (val&0xff); dst += ddir; val >>= 8; __sz--; \ case 3: *dst = (val&0xff); dst += ddir; val >>= 8; __sz--; \ case 2: *dst = (val&0xff); dst += ddir; val >>= 8; __sz--; \ case 1: *dst = (val&0xff); dst += ddir; val >>= 8; __sz--; \ } \ } \ } while(0)/* calculate a - *cp (carry) (store result in b), *cp is updated! */#define SUBc(a, cp, b) do { \ byte __x = (a); \ byte __y = (__x - (*(cp))); \ (*cp) = (__y > __x); \ *(b) = ~__y; \ } while(0) static intfmt_int(byte *buf, Uint sz, Eterm val, Uint size, Uint flags){ unsigned long offs; if (size == 0) { return 0; } offs = BIT_OFFSET(size); if (is_small(val)) { Sint v = signed_val(val); if (flags & BSF_LITTLE) { /* Little endian */ sz--; COPY_VAL(buf,1,v,sz); *buf = offs ? ((v << (8-offs)) & 0xff) : (v & 0xff); } else { /* Big endian */ buf += (sz - 1); if (offs) { *buf-- = (v << (8-offs)) & 0xff; sz--; v >>= offs; } COPY_VAL(buf,-1,v,sz); } } else if (is_big(val)) { int sign = big_sign(val); Uint ds = big_size(val)*sizeof(digit_t); /* number of digits bytes */ digit_t* dp = big_v(val); int n = MIN(sz,ds); if (flags & BSF_LITTLE) { sz -= n; /* pad with this amount */ if (sign) { int c = 1; while(n >= sizeof(digit_t)) { digit_t d = *dp++; int i; for(i = 0; i < sizeof(digit_t); ++i) { SUBc((d&0xff), &c, buf); buf++; d >>= 8; } n -= sizeof(digit_t); } if (n) { digit_t d = *dp; do { SUBc((d&0xff), &c, buf); buf++; d >>= 8; } while (--n > 0); } /* pad */ while(sz--) { SUBc(0, &c, buf); buf++; } } else { while(n >= sizeof(digit_t)) { digit_t d = *dp++; int i; for(i = 0; i < sizeof(digit_t); ++i) { *buf++ = (d & 0xff); d >>= 8; } n -= sizeof(digit_t); } if (n) { digit_t d = *dp; do { *buf++ = (d & 0xff); d >>= 8; } while (--n > 0); } /* pad */ while(sz) { *buf++ = 0; sz--; } } /* adjust MSB!!! */ if (offs) { buf--; *buf <<= (8 - offs); } } else { /* BIG ENDIAN */ Uint acc = 0; /* acc must be large enough to fit two digits */ buf += (sz - 1); /* end of buffer */ sz -= n; /* pad with this amount */ offs = offs ? (8-offs) : 0; /* shift offset */ if (sign) { /* SIGNED */ int c = 1; while(n >= sizeof(digit_t)) { int i; acc |= (*dp++ << offs); for(i = 0; i < sizeof(digit_t); ++i) { SUBc((acc&0xff), &c, buf); buf--; acc >>= 8; } n -= sizeof(digit_t); } if (n) { acc |= (*dp << offs); do { SUBc((acc & 0xff), &c, buf); buf--; acc >>= 8; } while (--n > 0); } /* pad */ while(sz--) { SUBc((acc & 0xff), &c, buf); buf--; acc >>= 8; } } else { /* UNSIGNED */ while(n >= sizeof(digit_t)) { int i; acc |= (*dp++ << offs); for(i = 0; i < sizeof(digit_t); ++i) { *buf-- = (acc & 0xff); acc >>= 8; } n -= sizeof(digit_t); } if (n) { acc |= (*dp << offs); do { *buf-- = acc & 0xff; acc >>= 8; } while (--n > 0); } while(sz--) { *buf-- = acc & 0xff; acc >>= 8; } } } } else { /* Neither small nor big */ return -1; } return 0;}static voidERTS_INLINE need_byte_buf(ERL_BITS_PROTO_1(int need)){ if (byte_buf_len < need) {#ifdef ERTS_SMP erts_smp_atomic_add(&bits_bufs_size, need - byte_buf_len);#endif byte_buf_len = need; byte_buf = erts_realloc(ERTS_ALC_T_BITS_BUF, byte_buf, byte_buf_len); }}interts_new_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) { if (fmt_int(erts_current_bin+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; } erts_copy_bits(iptr, 0, 1, erts_current_bin, bin_offset, 1, num_bits); } erts_bin_offset = bin_offset + num_bits; return 1;}interts_new_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; } copy_binary_to_buffer(erts_current_bin, erts_bin_offset, bptr, bitoffs, num_bits); erts_bin_offset += num_bits; return 1;}interts_new_bs_put_binary_all(ERL_BITS_PROTO_1(Eterm arg)){ byte *bptr; Uint bitoffs; Uint bitsize; Uint num_bits; if (!is_binary(arg)) { return 0; } ERTS_GET_BINARY_BYTES(arg, bptr, bitoffs, bitsize); num_bits = 8*binary_size(arg)+bitsize; copy_binary_to_buffer(erts_current_bin, erts_bin_offset, bptr, bitoffs, num_bits); erts_bin_offset += num_bits; return 1;}interts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags){ ERL_BITS_DEFINE_STATEP(c_p); if (BIT_OFFSET(erts_bin_offset) == 0) { Uint32 a; Uint32 b; if (num_bits == 64) { union { double f64; Uint32 i32[2]; } u; if (is_float(arg)) { FloatDef *fdp = (FloatDef*)(float_val(arg) + 1); a = fdp->fw[0]; b = fdp->fw[1]; } else if (is_small(arg)) { u.f64 = (double) signed_val(arg); a = u.i32[0]; b = u.i32[1]; } else if (is_big(arg)) { if (big_to_double(arg, &u.f64) < 0) { return 0; } a = u.i32[0]; b = u.i32[1]; } else { return 0; } } else if (num_bits == 32) { union { float f32; Uint32 i32; } u; b = 0; if (is_float(arg)) { FloatDef f; GET_DOUBLE(arg, f); ERTS_FP_CHECK_INIT(c_p); u.f32 = f.fd; ERTS_FP_ERROR(c_p,u.f32,;); a = u.i32; } else if (is_small(arg)) { u.f32 = (float) signed_val(arg); a = u.i32; } else if (is_big(arg)) { double f64; if (big_to_double(arg, &f64) < 0) { return 0; } ERTS_FP_CHECK_INIT(c_p); u.f32 = (float) f64; ERTS_FP_ERROR(c_p,u.f32,;); a = u.i32; } else { return 0; } } else { return 0; } if (BIT_IS_MACHINE_ENDIAN(flags)) { byte* t = erts_current_bin+BYTE_OFFSET(erts_bin_offset);#ifdef WORDS_BIGENDIAN t[0] = a >> 24; t[1] = a >> 16; t[2] = a >> 8; t[3] = a; if (num_bits == 64) { t[4] = b >> 24; t[5] = b >> 16; t[6] = b >> 8; t[7] = b; }#else t[3] = a >> 24; t[2] = a >> 16; t[1] = a >> 8; t[0] = a;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -