diff options
author | Sverker Eriksson <[email protected]> | 2015-08-26 15:43:00 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2015-11-04 15:44:15 +0100 |
commit | 5b600aac42fdc4d08fabba682d7803351c9bfbdb (patch) | |
tree | b16ea960a2506ddaa1be6b1cbf576e5ac64b97a8 /erts/emulator/beam | |
parent | 20855f1819f91eeeb1fa746186477d3824024500 (diff) | |
download | otp-5b600aac42fdc4d08fabba682d7803351c9bfbdb.tar.gz otp-5b600aac42fdc4d08fabba682d7803351c9bfbdb.tar.bz2 otp-5b600aac42fdc4d08fabba682d7803351c9bfbdb.zip |
erts: Refactor backend of binary:split
to reduce code volume.
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/erl_bif_binary.c | 659 |
1 files changed, 151 insertions, 508 deletions
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c index 860c9a9779..6adc61df19 100644 --- a/erts/emulator/beam/erl_bif_binary.c +++ b/erts/emulator/beam/erl_bif_binary.c @@ -2542,6 +2542,11 @@ BIF_RETTYPE binary_copy_2(BIF_ALIST_2) return do_binary_copy(BIF_P,BIF_ARG_1,BIF_ARG_2); } +static Eterm do_split_single_result(Process*, Eterm subject, + Sint pos, Sint len, Uint hsflags); +static Eterm do_split_global_result(Process*, FindallData *fad, Uint fad_sz, + Eterm subject, Uint hsflags); + #define BINARY_SPLIT_GLOBAL 0x01 #define BINARY_SPLIT_TRIM 0x02 #define BINARY_SPLIT_TRIM_ALL 0x04 @@ -2571,7 +2576,6 @@ static int do_binary_split(Process *p, Eterm subject, Uint hsstart, if (type == am_bm) { BMData *bm; Sint pos; - Eterm ret; Eterm *hp; BMFindAllState state; Uint reds = get_reds(p, BM_LOOP_FACTOR); @@ -2591,8 +2595,7 @@ static int do_binary_split(Process *p, Eterm subject, Uint hsstart, pos = bm_find_all_non_overlapping(&state, bm, bytes, &reds); if (pos == BM_NOT_FOUND) { hp = HAlloc(p, 2); - ret = NIL; - ret = CONS(hp, subject, ret); + *res_term = CONS(hp, subject, NIL); } else if (pos == BM_RESTART) { int x = (SIZEOF_BM_SERIALIZED_FIND_ALL_STATE(state) / sizeof(Eterm)) + @@ -2610,196 +2613,16 @@ static int do_binary_split(Process *p, Eterm subject, Uint hsstart, bm_clean_find_all(&state); return DO_BIN_MATCH_RESTART; } else { - size_t orig_size; - Eterm orig; - Uint offset; - Uint bit_offset; - Uint bit_size; - ErlSubBin *sb; - FindallData *fad = state.out; - Sint i, j; - Sint drop = 0; - Sint head = 0; - Sint tail; - Uint list_size; - Uint tail_pos; - - tail = state.m - 1; - list_size = state.m + 1; - orig_size = binary_size(subject); - tail_pos = (Uint)(orig_size); - - if (hsflags & (BINARY_SPLIT_TRIM | BINARY_SPLIT_TRIM_ALL)) { - if ((orig_size - fad[tail].pos - fad[tail].len) == 0) { - list_size--; - for (i = (tail - 1); i >= 0; --i) { - if ((fad[i+1].pos - fad[i].pos - fad[i].len) != 0) { - break; - } - list_size--; - } - if (i == -1) { - if (fad[head].pos == 0) { - ret = NIL; - } else { - hp = HAlloc(p, (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = fad[head].pos; - sb->offs = offset; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = bit_size; - sb->is_writable = 0; - fad[head].epos = make_binary(sb); - hp += ERL_SUB_BIN_SIZE; - - ret = NIL; - ret = CONS(hp, make_binary(sb), ret); - hp += 2; - } - erts_free_aligned_binary_bytes(temp_alloc); - bm_clean_find_all(&state); - BUMP_REDS(p, (save_reds - reds) / BM_LOOP_FACTOR); - *res_term = ret; - return DO_BIN_MATCH_OK; - } - tail = i; - tail_pos = fad[tail+1].pos; - } - } - if (hsflags & BINARY_SPLIT_TRIM_ALL) { - if (fad[head].pos == 0) { - drop++; - list_size--; - for (i = drop, j = tail; i <= j; ++i) { - if ((fad[i].pos - fad[i-1].pos - fad[i-1].len) != 0) { - break; - } - drop++; - list_size--; - } - head = drop - 1; - } - for (i = (head+1), j = tail; i <= j; ++i) { - if ((fad[i].pos - fad[i-1].pos - fad[i-1].len) == 0) { - list_size--; - } - } - - hp = HAlloc(p, list_size * (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - - if (drop == 0) { - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = fad[head].pos; - sb->offs = offset; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - fad[head].epos = make_binary(sb); - hp += ERL_SUB_BIN_SIZE; - } - - for (i = (head+1), j = tail; i <= j; ++i) { - if ((fad[i].pos - fad[i-1].pos - fad[i-1].len) != 0) { - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = fad[i].pos - fad[i-1].pos - fad[i-1].len; - sb->offs = offset + fad[i-1].pos + fad[i-1].len; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - fad[i].epos = make_binary(sb); - hp += ERL_SUB_BIN_SIZE; - } - } - - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = tail_pos - fad[tail].pos - fad[tail].len; - sb->offs = offset + fad[tail].pos + fad[tail].len; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = bit_size; - sb->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - ret = NIL; - ret = CONS(hp, make_binary(sb), ret); - hp += 2; - for (i = tail, j = head; i > j; --i) { - if ((fad[i].pos - fad[i-1].pos - fad[i-1].len) != 0) { - ret = CONS(hp, fad[i].epos, ret); - hp += 2; - } - } - if (drop == 0) { - ret = CONS(hp, fad[head].epos, ret); - hp += 2; - } - } else { - hp = HAlloc(p, list_size * (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = fad[head].pos; - sb->offs = offset; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - fad[head].epos = make_binary(sb); - hp += ERL_SUB_BIN_SIZE; - - for (i = (head+1), j = tail; i <= j; ++i) { - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = fad[i].pos - fad[i-1].pos - fad[i-1].len; - sb->offs = offset + fad[i-1].pos + fad[i-1].len; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - fad[i].epos = make_binary(sb); - hp += ERL_SUB_BIN_SIZE; - } - - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = tail_pos - fad[tail].pos - fad[tail].len; - sb->offs = offset + fad[tail].pos + fad[tail].len; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = bit_size; - sb->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - ret = NIL; - ret = CONS(hp, make_binary(sb), ret); - hp += 2; - for (i = tail, j = head; i >= j; --i) { - ret = CONS(hp, fad[i].epos, ret); - hp += 2; - } - } + *res_term = do_split_global_result(p, state.out, state.m, subject, hsflags); } erts_free_aligned_binary_bytes(temp_alloc); bm_clean_find_all(&state); BUMP_REDS(p, (save_reds - reds) / BM_LOOP_FACTOR); - *res_term = ret; return DO_BIN_MATCH_OK; } else if (type == am_ac) { ACTrie *act; int acr; ACFindAllState state; - Eterm ret; Eterm *hp; Uint reds = get_reds(p, AC_LOOP_FACTOR); Uint save_reds = reds; @@ -2817,8 +2640,7 @@ static int do_binary_split(Process *p, Eterm subject, Uint hsstart, acr = ac_find_all_non_overlapping(&state, bytes, &reds); if (acr == AC_NOT_FOUND) { hp = HAlloc(p, 2); - ret = NIL; - ret = CONS(hp, subject, ret); + *res_term = CONS(hp, subject, NIL); } else if (acr == AC_RESTART) { int x = (SIZEOF_AC_SERIALIZED_FIND_ALL_STATE(state) / sizeof(Eterm)) + !!(SIZEOF_AC_SERIALIZED_FIND_ALL_STATE(state) % sizeof(Eterm)); @@ -2835,197 +2657,17 @@ static int do_binary_split(Process *p, Eterm subject, Uint hsstart, ac_clean_find_all(&state); return DO_BIN_MATCH_RESTART; } else { - size_t orig_size; - Eterm orig; - Uint offset; - Uint bit_offset; - Uint bit_size; - ErlSubBin *sb; - FindallData *fad = state.out; - Sint i, j; - Sint drop = 0; - Sint head = 0; - Sint tail; - Uint list_size; - Uint tail_pos; - - tail = state.m - 1; - list_size = state.m + 1; - orig_size = binary_size(subject); - tail_pos = (Uint)(orig_size); - - if (hsflags & (BINARY_SPLIT_TRIM | BINARY_SPLIT_TRIM_ALL)) { - if ((orig_size - fad[tail].pos - fad[tail].len) == 0) { - list_size--; - for (i = (tail - 1); i >= 0; --i) { - if ((fad[i+1].pos - fad[i].pos - fad[i].len) != 0) { - break; - } - list_size--; - } - if (i == -1) { - if (fad[head].pos == 0) { - ret = NIL; - } else { - hp = HAlloc(p, (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = fad[head].pos; - sb->offs = offset; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = bit_size; - sb->is_writable = 0; - fad[head].epos = make_binary(sb); - hp += ERL_SUB_BIN_SIZE; - - ret = NIL; - ret = CONS(hp, make_binary(sb), ret); - hp += 2; - } - erts_free_aligned_binary_bytes(temp_alloc); - ac_clean_find_all(&state); - BUMP_REDS(p, (save_reds - reds) / AC_LOOP_FACTOR); - *res_term = ret; - return DO_BIN_MATCH_OK; - } - tail = i; - tail_pos = fad[tail+1].pos; - } - } - if (hsflags & BINARY_SPLIT_TRIM_ALL) { - if (fad[head].pos == 0) { - drop++; - list_size--; - for (i = drop, j = tail; i <= j; ++i) { - if ((fad[i].pos - fad[i-1].pos - fad[i-1].len) != 0) { - break; - } - drop++; - list_size--; - } - head = drop - 1; - } - for (i = (head+1), j = tail; i <= j; ++i) { - if ((fad[i].pos - fad[i-1].pos - fad[i-1].len) == 0) { - list_size--; - } - } - - hp = HAlloc(p, list_size * (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - - if (drop == 0) { - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = fad[head].pos; - sb->offs = offset; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - fad[head].epos = make_binary(sb); - hp += ERL_SUB_BIN_SIZE; - } - - for (i = (head+1), j = tail; i <= j; ++i) { - if ((fad[i].pos - fad[i-1].pos - fad[i-1].len) != 0) { - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = fad[i].pos - fad[i-1].pos - fad[i-1].len; - sb->offs = offset + fad[i-1].pos + fad[i-1].len; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - fad[i].epos = make_binary(sb); - hp += ERL_SUB_BIN_SIZE; - } - } - - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = tail_pos - fad[tail].pos - fad[tail].len; - sb->offs = offset + fad[tail].pos + fad[tail].len; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = bit_size; - sb->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - ret = NIL; - ret = CONS(hp, make_binary(sb), ret); - hp += 2; - for (i = tail, j = head; i > j; --i) { - if ((fad[i].pos - fad[i-1].pos - fad[i-1].len) != 0) { - ret = CONS(hp, fad[i].epos, ret); - hp += 2; - } - } - if (drop == 0) { - ret = CONS(hp, fad[head].epos, ret); - hp += 2; - } - } else { - hp = HAlloc(p, list_size * (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = fad[head].pos; - sb->offs = offset; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - fad[head].epos = make_binary(sb); - hp += ERL_SUB_BIN_SIZE; - - for (i = (head+1), j = tail; i <= j; ++i) { - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = fad[i].pos - fad[i-1].pos - fad[i-1].len; - sb->offs = offset + fad[i-1].pos + fad[i-1].len; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - fad[i].epos = make_binary(sb); - hp += ERL_SUB_BIN_SIZE; - } - - sb = (ErlSubBin *)(hp); - sb->thing_word = HEADER_SUB_BIN; - sb->size = tail_pos - fad[tail].pos - fad[tail].len; - sb->offs = offset + fad[tail].pos + fad[tail].len; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = bit_size; - sb->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - ret = NIL; - ret = CONS(hp, make_binary(sb), ret); - hp += 2; - for (i = tail, j = head; i >= j; --i) { - ret = CONS(hp, fad[i].epos, ret); - hp += 2; - } - } + *res_term = do_split_global_result(p, state.out, state.m, subject, hsflags); } erts_free_aligned_binary_bytes(temp_alloc); ac_clean_find_all(&state); BUMP_REDS(p, (save_reds - reds) / AC_LOOP_FACTOR); - *res_term = ret; return DO_BIN_MATCH_OK; } } else { if (type == am_bm) { BMData *bm; Sint pos; - Eterm ret; Eterm *hp; BMFindFirstState state; Uint reds = get_reds(p, BM_LOOP_FACTOR); @@ -3049,8 +2691,7 @@ static int do_binary_split(Process *p, Eterm subject, Uint hsstart, pos = bm_find_first_match(&state, bm, bytes, &reds); if (pos == BM_NOT_FOUND) { hp = HAlloc(p, 2); - ret = NIL; - ret = CONS(hp, subject, ret); + *res_term = CONS(hp, subject, NIL); } else if (pos == BM_RESTART) { int x = (sizeof(state) / sizeof(Eterm)) + @@ -3067,84 +2708,16 @@ static int do_binary_split(Process *p, Eterm subject, Uint hsstart, erts_free_aligned_binary_bytes(temp_alloc); return DO_BIN_MATCH_RESTART; } else { - size_t orig_size; - Eterm orig; - Uint offset; - Uint bit_offset; - Uint bit_size; - ErlSubBin *sb1; - ErlSubBin *sb2; - - orig_size = binary_size(subject); - - if ((hsflags & (BINARY_SPLIT_TRIM | BINARY_SPLIT_TRIM_ALL)) && (orig_size - pos - bm->len) == 0) { - if (pos == 0) { - ret = NIL; - } else { - hp = HAlloc(p, (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - sb1 = (ErlSubBin *) hp; - sb1->thing_word = HEADER_SUB_BIN; - sb1->size = pos; - sb1->offs = offset; - sb1->orig = orig; - sb1->bitoffs = bit_offset; - sb1->bitsize = bit_size; - sb1->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - ret = NIL; - ret = CONS(hp, make_binary(sb1), ret); - hp += 2; - } - } else { - if ((hsflags & BINARY_SPLIT_TRIM_ALL) && (pos == 0)) { - hp = HAlloc(p, 1 * (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - sb1 = NULL; - } else { - hp = HAlloc(p, 2 * (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - sb1 = (ErlSubBin *) hp; - sb1->thing_word = HEADER_SUB_BIN; - sb1->size = pos; - sb1->offs = offset; - sb1->orig = orig; - sb1->bitoffs = bit_offset; - sb1->bitsize = 0; - sb1->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - } - - sb2 = (ErlSubBin *) hp; - sb2->thing_word = HEADER_SUB_BIN; - sb2->size = orig_size - pos - bm->len; - sb2->offs = offset + pos + bm->len; - sb2->orig = orig; - sb2->bitoffs = bit_offset; - sb2->bitsize = bit_size; - sb2->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - ret = NIL; - ret = CONS(hp, make_binary(sb2), ret); - hp += 2; - if (sb1 != NULL) { - ret = CONS(hp, make_binary(sb1), ret); - hp += 2; - } - } + *res_term = do_split_single_result(p, subject, pos, bm->len, hsflags); } erts_free_aligned_binary_bytes(temp_alloc); BUMP_REDS(p, (save_reds - reds) / BM_LOOP_FACTOR); - *res_term = ret; return DO_BIN_MATCH_OK; } else if (type == am_ac) { ACTrie *act; Uint pos, rlen; int acr; ACFindFirstState state; - Eterm ret; Eterm *hp; Uint reds = get_reds(p, AC_LOOP_FACTOR); Uint save_reds = reds; @@ -3162,8 +2735,7 @@ static int do_binary_split(Process *p, Eterm subject, Uint hsstart, acr = ac_find_first_match(&state, bytes, &pos, &rlen, &reds); if (acr == AC_NOT_FOUND) { hp = HAlloc(p, 2); - ret = NIL; - ret = CONS(hp, subject, ret); + *res_term = CONS(hp, subject, NIL); } else if (acr == AC_RESTART) { int x = (sizeof(state) / sizeof(Eterm)) + @@ -3180,77 +2752,10 @@ static int do_binary_split(Process *p, Eterm subject, Uint hsstart, erts_free_aligned_binary_bytes(temp_alloc); return DO_BIN_MATCH_RESTART; } else { - size_t orig_size; - Eterm orig; - Uint offset; - Uint bit_offset; - Uint bit_size; - ErlSubBin *sb1; - ErlSubBin *sb2; - - orig_size = binary_size(subject); - - if ((hsflags & (BINARY_SPLIT_TRIM | BINARY_SPLIT_TRIM_ALL)) && (orig_size - pos - rlen) == 0) { - if (pos == 0) { - ret = NIL; - } else { - hp = HAlloc(p, (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - sb1 = (ErlSubBin *) hp; - sb1->thing_word = HEADER_SUB_BIN; - sb1->size = pos; - sb1->offs = offset; - sb1->orig = orig; - sb1->bitoffs = bit_offset; - sb1->bitsize = bit_size; - sb1->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - ret = NIL; - ret = CONS(hp, make_binary(sb1), ret); - hp += 2; - } - } else { - if ((hsflags & BINARY_SPLIT_TRIM_ALL) && (pos == 0)) { - hp = HAlloc(p, 2 * (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - sb1 = NULL; - } else { - hp = HAlloc(p, 2 * (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - sb1 = (ErlSubBin *) hp; - sb1->thing_word = HEADER_SUB_BIN; - sb1->size = pos; - sb1->offs = offset; - sb1->orig = orig; - sb1->bitoffs = bit_offset; - sb1->bitsize = 0; - sb1->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - } - - sb2 = (ErlSubBin *) hp; - sb2->thing_word = HEADER_SUB_BIN; - sb2->size = orig_size - pos - rlen; - sb2->offs = offset + pos + rlen; - sb2->orig = orig; - sb2->bitoffs = bit_offset; - sb2->bitsize = bit_size; - sb2->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - ret = NIL; - ret = CONS(hp, make_binary(sb2), ret); - hp += 2; - if (sb1 != NULL) { - ret = CONS(hp, make_binary(sb1), ret); - hp += 2; - } - } + *res_term = do_split_single_result(p, subject, pos, rlen, hsflags); } erts_free_aligned_binary_bytes(temp_alloc); BUMP_REDS(p, (save_reds - reds) / AC_LOOP_FACTOR); - *res_term = ret; return DO_BIN_MATCH_OK; } } @@ -3258,6 +2763,144 @@ static int do_binary_split(Process *p, Eterm subject, Uint hsstart, return DO_BIN_MATCH_BADARG; } +static Eterm do_split_single_result(Process* p, Eterm subject, + Sint pos, Sint len, Uint hsflags) +{ + size_t orig_size; + Eterm orig; + Uint offset; + Uint bit_offset; + Uint bit_size; + ErlSubBin *sb1; + ErlSubBin *sb2; + Eterm* hp; + Eterm ret; + + orig_size = binary_size(subject); + + if ((hsflags & (BINARY_SPLIT_TRIM | BINARY_SPLIT_TRIM_ALL)) && (orig_size - pos - len) == 0) { + if (pos != 0) { + ret = NIL; + } else { + hp = HAlloc(p, (ERL_SUB_BIN_SIZE + 2)); + ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); + sb1 = (ErlSubBin *) hp; + sb1->thing_word = HEADER_SUB_BIN; + sb1->size = pos; + sb1->offs = offset; + sb1->orig = orig; + sb1->bitoffs = bit_offset; + sb1->bitsize = bit_size; + sb1->is_writable = 0; + hp += ERL_SUB_BIN_SIZE; + + ret = CONS(hp, make_binary(sb1), NIL); + hp += 2; + } + } else { + if ((hsflags & BINARY_SPLIT_TRIM_ALL) && (pos == 0)) { + hp = HAlloc(p, 1 * (ERL_SUB_BIN_SIZE + 2)); + ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); + sb1 = NULL; + } else { + hp = HAlloc(p, 2 * (ERL_SUB_BIN_SIZE + 2)); + ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); + sb1 = (ErlSubBin *) hp; + sb1->thing_word = HEADER_SUB_BIN; + sb1->size = pos; + sb1->offs = offset; + sb1->orig = orig; + sb1->bitoffs = bit_offset; + sb1->bitsize = 0; + sb1->is_writable = 0; + hp += ERL_SUB_BIN_SIZE; + } + + sb2 = (ErlSubBin *) hp; + sb2->thing_word = HEADER_SUB_BIN; + sb2->size = orig_size - pos - len; + sb2->offs = offset + pos + len; + sb2->orig = orig; + sb2->bitoffs = bit_offset; + sb2->bitsize = bit_size; + sb2->is_writable = 0; + hp += ERL_SUB_BIN_SIZE; + + ret = CONS(hp, make_binary(sb2), NIL); + hp += 2; + if (sb1 != NULL) { + ret = CONS(hp, make_binary(sb1), ret); + hp += 2; + } + } + return ret; +} + +static Eterm do_split_global_result(Process* p, FindallData *fad, Uint fad_sz, + Uint subject, Uint hsflags) +{ + size_t orig_size; + Eterm orig; + Uint offset; + Uint bit_offset; + Uint bit_size; + ErlSubBin *sb; + Sint i; + Sint tail; + Uint list_size; + Uint end_pos; + Uint do_trim = hsflags & (BINARY_SPLIT_TRIM | BINARY_SPLIT_TRIM_ALL); + Eterm* hp; + Eterm* hendp; + Eterm ret; + + tail = fad_sz - 1; + list_size = fad_sz + 1; + orig_size = binary_size(subject); + end_pos = (Uint)(orig_size); + + hp = HAlloc(p, list_size * (ERL_SUB_BIN_SIZE + 2)); + hendp = hp + list_size * (ERL_SUB_BIN_SIZE + 2); + ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); + ASSERT(bit_size == 0); + + ret = NIL; + + for (i = tail; i >= 0; --i) { + sb = (ErlSubBin *)(hp); + sb->size = end_pos - (fad[i].pos + fad[i].len); + if (!(sb->size == 0 && do_trim)) { + sb->thing_word = HEADER_SUB_BIN; + sb->offs = offset + fad[i].pos + fad[i].len; + sb->orig = orig; + sb->bitoffs = bit_offset; + sb->bitsize = 0; + sb->is_writable = 0; + hp += ERL_SUB_BIN_SIZE; + ret = CONS(hp, make_binary(sb), ret); + hp += 2; + do_trim &= ~BINARY_SPLIT_TRIM; + } + end_pos = fad[i].pos; + } + + sb = (ErlSubBin *)(hp); + sb->size = fad[0].pos; + if (!(sb->size == 0 && do_trim)) { + sb->thing_word = HEADER_SUB_BIN; + sb->offs = offset; + sb->orig = orig; + sb->bitoffs = bit_offset; + sb->bitsize = 0; + sb->is_writable = 0; + hp += ERL_SUB_BIN_SIZE; + ret = CONS(hp, make_binary(sb), ret); + hp += 2; + } + HRelease(p, hendp, hp); + return ret; +} + static int parse_split_opts_list(Eterm l, Eterm bin, Uint *posp, Uint *endp, Uint *optp) { Eterm *tp; |