30
30
#include "erl_binary.h"
33
33
Uint erts_allocated_binaries;
34
erts_mtx_t erts_bin_alloc_mtx;
36
37
erts_init_binary(void)
38
39
erts_allocated_binaries = 0;
40
erts_mtx_init(&erts_bin_alloc_mtx, "binary_alloc");
42
/* Verify Binary alignment... */
43
if ((((Uint) &((Binary *) 0)->orig_bytes[0]) % ((Uint) 8)) != 0) {
44
/* I assume that any compiler should be able to optimize this
45
away. If not, this test is not very expensive... */
46
erl_exit(ERTS_ABORT_EXIT,
47
"Internal error: Address of orig_bytes[0] of a Binary"
48
"is *not* 8-byte aligned\n");
164
177
newbin->orig_size = size;
165
178
pb->val = newbin;
167
pb->bytes = newbin->orig_bytes;
180
pb->bytes = (byte*) newbin->orig_bytes;
168
181
bin = make_binary(pb);
187
erts_get_aligned_binary_bytes(Eterm bin, byte** base_ptr)
195
if (is_not_binary(bin)) {
198
byte_size = binary_size(bin);
199
real_bin = binary_val(bin);
200
if (*real_bin == HEADER_SUB_BIN) {
201
ErlSubBin* sb = (ErlSubBin *) real_bin;
206
bit_offs = sb->bitoffs;
207
real_bin = binary_val(sb->orig);
209
if (*real_bin == HEADER_PROC_BIN) {
210
bytes = ((ProcBin *) real_bin)->bytes + offs;
212
bytes = (byte *)(&(((ErlHeapBin *) real_bin)->data)) + offs;
215
byte* buf = (byte *) erts_alloc(ERTS_ALC_T_TMP, byte_size);
217
erts_copy_bits(bytes, bit_offs, 1, buf, 0, 1, byte_size*8);
225
bin_bytes_to_list(Eterm previous, Eterm* hp, byte* bytes, Uint size, Uint bitoffs)
229
previous = CONS(hp, make_small(bytes[--size]), previous);
238
next = bytes[--size];
239
previous = CONS(hp, make_small(((present >> (8-bitoffs)) |
240
(next << bitoffs)) & 255), previous);
173
248
BIF_RETTYPE binary_to_list_1(BIF_ALIST_1)
256
Eterm previous = NIL;
180
259
if (is_not_binary(BIF_ARG_1)) {
181
260
BIF_ERROR(BIF_P, BADARG);
184
262
size = binary_size(BIF_ARG_1);
185
hp = HAlloc(BIF_P, 2 * size);
186
GET_BINARY_BYTES(BIF_ARG_1, bufp);
263
ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, offset, bitoffs, bitsize);
264
bytes = binary_bytes(real_bin)+offset;
266
hp = HAlloc(BIF_P, 2 * size);
190
previous = CONS(hp, make_small(bufp[--size]), previous);
270
hp = HAlloc(BIF_P, ERL_SUB_BIN_SIZE+2+2*size);
271
last = (ErlSubBin *) hp;
272
last->thing_word = HEADER_SUB_BIN;
274
last->bitsize = bitsize;
275
last->offs = offset+size;
276
last->bitoffs = bitoffs;
277
last->orig = real_bin;
278
hp += ERL_SUB_BIN_SIZE;
279
previous = CONS(hp, make_binary(last), previous);
282
BIF_RET(bin_bytes_to_list(previous, hp, bytes, size, bitoffs));
196
285
BIF_RETTYPE binary_to_list_3(BIF_ALIST_3)
206
296
if (is_not_binary(BIF_ARG_1)) {
298
BIF_ERROR(BIF_P, BADARG);
209
300
if (!term_to_Uint(BIF_ARG_2, &start) || !term_to_Uint(BIF_ARG_3, &stop)) {
212
303
size = binary_size(BIF_ARG_1);
213
GET_BINARY_BYTES(BIF_ARG_1, bytes);
214
if (start < 1 || start > size || stop < 1 || stop > size || stop < start) {
304
ERTS_GET_BINARY_BYTES(BIF_ARG_1, bytes, bitoffs, bitsize);
305
if (start < 1 || start > size || stop < 1 ||
306
stop > size || stop < start || bitsize != 0) {
218
309
i = stop-start+1;
219
310
hp = HAlloc(BIF_P, 2*i);
223
previous = CONS(hp, make_small(*--bytes), previous);
229
BIF_ERROR(BIF_P, BADARG);
311
BIF_RET(bin_bytes_to_list(NIL, hp, bytes+start-1, i, bitoffs));
236
318
BIF_RETTYPE list_to_binary_1(BIF_ALIST_1)
242
if (is_nil(BIF_ARG_1)) {
243
BIF_RET(new_binary(BIF_P,(byte*)"",0));
245
if (is_not_list(BIF_ARG_1)) {
247
BIF_ERROR(BIF_P, BADARG);
249
if ((i = io_list_len(BIF_ARG_1)) < 0) {
252
bin = new_binary(BIF_P, (byte *)NULL, i);
253
GET_BINARY_BYTES(bin, bytes);
254
if (io_list_to_buf(BIF_ARG_1, (char*) bytes, i) < 0) {
326
if (is_nil(BIF_ARG_1)) {
327
BIF_RET(new_binary(BIF_P,(byte*)"",0));
329
if (is_not_list(BIF_ARG_1)) {
331
BIF_ERROR(BIF_P, BADARG);
333
if ((i = io_list_len(BIF_ARG_1)) < 0) {
336
bin = new_binary(BIF_P, (byte *)NULL, i);
337
bytes = binary_bytes(bin);
338
offset = io_list_to_buf2(BIF_ARG_1, (char*) bytes, i);
341
} else if (offset > 0) {
342
hp = HAlloc(BIF_P, ERL_SUB_BIN_SIZE);
343
sb1 = (ErlSubBin *) hp;
344
sb1->thing_word = HEADER_SUB_BIN;
349
sb1->bitsize = offset;
350
hp += ERL_SUB_BIN_SIZE;
351
bin = make_binary(sb1);
357
/* Turn a possibly deep list of ints (and binaries) into */
358
/* One large binary object */
360
BIF_RETTYPE iolist_to_binary_1(BIF_ALIST_1)
368
if (is_binary(BIF_ARG_1)) {
371
if (is_nil(BIF_ARG_1)) {
372
BIF_RET(new_binary(BIF_P,(byte*)"",0));
374
if (is_not_list(BIF_ARG_1)) {
376
BIF_ERROR(BIF_P, BADARG);
378
if ((i = io_list_len(BIF_ARG_1)) < 0) {
381
bin = new_binary(BIF_P, (byte *)NULL, i);
382
bytes = binary_bytes(bin);
383
if ((offset = io_list_to_buf(BIF_ARG_1, (char*) bytes, i)) < 0) {
385
} else if (offset > 0) {
386
hp = HAlloc(BIF_P, ERL_SUB_BIN_SIZE);
387
sb1 = (ErlSubBin *) hp;
388
sb1->thing_word = HEADER_SUB_BIN;
393
sb1->bitsize = offset;
394
hp += ERL_SUB_BIN_SIZE;
395
bin = make_binary(sb1);