Skip to content

Commit 5b4ac54

Browse files
committed
towards segfault free implementation
1 parent f6f912b commit 5b4ac54

File tree

2 files changed

+60
-10
lines changed

2 files changed

+60
-10
lines changed

src/string_radix_sort.jl

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,63 @@ If the `String` is shorter than 8 bytes then it's padded with 0.
1212
- `s`: a `String`
1313
- `skipbytes`: how many bytes to skip e.g. load_bits("abc", 1) will load "bc" as bits
1414
"""
15-
function load_bits(::Type{T}, s::String, skipbytes = 0) where T
15+
# Some part of the return result should be padded with 0s.
16+
# To prevent any possibility of segfault we load the bits using
17+
# successively smaller types
18+
# it is assumed that the type you are trying to load into needs padding
19+
# i.e. `remaining_bytes_to_load > 0`
20+
function load_bits_with_padding(::Type{UInt128}, s::String, skipbytes = 0)
21+
n = sizeof(s)
22+
T = UInt128
23+
ns = (sizeof(T) - min(sizeof(T), n - skipbytes))*8
24+
remaining_bytes_to_load = sizeof(T) - ns÷8
25+
# start
26+
res = zero(T)
27+
shift_for_padding = sizeof(T)*8
28+
29+
smaller_types = [UInt64, UInt32, UInt16, UInt8]
30+
smaller_sizes = sizeof.(smaller_types)
31+
for (S, type_size) in zip(smaller_types,smaller_sizes)
32+
if remaining_bytes_to_load >= type_size
33+
res |= Base.zext_int(T, load_bits(UInt64, s, skipbytes)) << (shift_for_padding - type_size*8)
34+
skipbytes += type_size
35+
remaining_bytes_to_load -= type_size
36+
shift_for_padding -= type_size*8
37+
elseif remaining_bytes_to_load >= 4
38+
res |= Base.zext_int(T, load_bits(UInt32, s, skipbytes)) << (shift_for_padding - 32)
39+
skipbytes += 4
40+
remaining_bytes_to_load -= 4
41+
shift_for_padding -= 32
42+
elseif remaining_bytes_to_load >= 2
43+
res |= Base.zext_int(T, load_bits(UInt16, s, skipbytes)) << (shift_for_padding - 16)
44+
skipbytes += 2
45+
remaining_bytes_to_load -= 2
46+
shift_for_padding -= 16
47+
else
48+
res |= Base.zext_int(T, load_bits(UInt8, s, skipbytes)) << (shift_for_padding - 8)
49+
# skipbytes += 1
50+
remaining_bytes_to_load -= 1
51+
end
52+
println("got here3")
53+
println(res)
54+
ok += 1
55+
if ok == 3
56+
return
57+
end
58+
end
59+
return res
60+
end
61+
62+
function load_bits(::Type{T}, s::String, skipbytes = 0)::T where T <: Unsigned
1663
n = sizeof(s)
1764
if n < skipbytes
18-
return zero(T)
65+
res = zero(T)
1966
elseif n - skipbytes >= sizeof(T)
20-
return ntoh(unsafe_load(Ptr{T}(pointer(s, skipbytes+1))))
67+
res = ntoh(unsafe_load(Ptr{T}(pointer(s, skipbytes+1))))
2168
else
22-
ns = (sizeof(T) - min(sizeof(T), n - skipbytes))*8
23-
# Some part of the return result should be padded with 0s; it is
24-
# where the length of remaing part of string to be loaded is smaller
25-
# than the `sizeof(T)` load the bits of the string but erase the
26-
# part that should be padded with 0s by bit-shifting the part "out"
27-
# then "in"
28-
return (ntoh(unsafe_load(Ptr{T}(pointer(s, skipbytes+1)))) >> ns) << ns
69+
res = load_bits_with_padding(T, s, skipbytes)
2970
end
71+
return res
3072
end
3173

3274

src/test.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
s = "abcdefghijklmno"
2+
T = UInt128
3+
skipbytes = 0
4+
import SortingAlgorithms: StringRadixSort, StringRadixSortAlg
5+
import Base.Perm
6+
7+
include("string_radix_sort.jl")
8+
load_bits(UInt128,s)

0 commit comments

Comments
 (0)