Skip to content

Commit 101496c

Browse files
authored
Merge pull request #10 from nalimilan/nl/type
Add intern(::Type, ::AbstractString) to choose custom return type
2 parents f3b0e04 + 00df17e commit 101496c

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

src/corefunctionality.jl

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@
66

77
# NOTE: This code is carefully optimised. Do not tweak it (for readability or otherwise) without benchmarking
88
@inline function intern!(wkd::WeakKeyDict{K}, key)::K where K
9-
kk::K = convert(K, key)
10-
119
lock(wkd.lock)
1210
# hand positioning the locks and unlocks (rather than do block or try finally, seems to be faster)
13-
index = Base.ht_keyindex2(wkd.ht, kk) # returns index if present, or -index if not
11+
index = Base.ht_keyindex2(wkd.ht, key) # returns index if present, or -index if not
1412
# note hash of weakref is equal to the hash of value, so avoid constructing it if not required
1513
if index > 0
1614
# found it
@@ -20,6 +18,7 @@
2018
else
2119
# Not found, so add it,
2220
# and mark it as a reference we track to delete!
21+
kk::K = convert(K, key)
2322
finalizer(kk, wkd.finalizer) # finalizer is set on the strong ref
2423
@inbounds Base._setindex!(wkd.ht, nothing, WeakRef(kk), -index)
2524
unlock(wkd.lock)
@@ -40,19 +39,34 @@ end
4039

4140
###################################
4241

42+
"""
43+
intern(s::T)
44+
45+
Return a reference to a interned instance of `s`,
46+
adding it to the interning pool if it did not already exist.
47+
"""
4348
function intern(s::T)::T where T
44-
intern!(get_pool(T), s)
49+
intern(T, s)
4550
end
4651

47-
intern(s::String)=intern!(get_pool(String), s) # Break stack-overflow
52+
"""
53+
intern(::Type{T}, s)
4854
55+
Intern `s` as if it were type `T`, converting it if required.
56+
Note that this will lead to unexpected behavour if the type of `s`, and `T`,
57+
do not have equivalent equality and hash functions
58+
(i.e. this is not safe if `hash(s) != hash(convert(T, s))`).
59+
"""
60+
function intern(::Type{T}, s)::T where T
61+
intern!(get_pool(T), s)
62+
end
4963

5064

5165
"""
5266
Substrings are interned as their parent string type
5367
"""
5468
function intern(substr::SubString{T})::T where T
55-
intern(T(substr))
69+
intern(T, substr)
5670
end
5771

5872

test/REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
WeakRefStrings 0.4.4

test/all_kinds_of_types.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@ using InternedStrings
77
@test !(ex1==="ex")
88
ex2 = intern("ex")
99
@test ex1===ex2
10+
ex3 = intern(String, "ex")
11+
@test ex1===ex3
1012

1113

1214

1315
@testset "type inference" begin
1416
@test ex1 isa String
17+
@test ex2 isa String
1518
@inferred intern("ex")
19+
@inferred intern(String, "ex")
1620
end
1721
end
1822

@@ -21,17 +25,33 @@ end
2125
@testset "SubString" begin
2226
aa1, bb1, cc1 = intern.(split("aa bb cc"))
2327
aa2, bb2, cc2 = intern.(split("aa bb cc"))
28+
aa3, bb3, cc3 = intern.(String, split("aa bb cc"))
2429

2530
@test bb1=="bb"
2631
@test !(bb1==="bb")
2732
@test bb1===bb2
33+
@test bb1===bb3
2834

2935
@testset "type inference" begin
3036
@test intern(split("aa bb cc")[1]) isa String
3137
@inferred intern(split("aa bb cc")[1])
38+
@test intern(String, split("aa bb cc")[1]) isa String
39+
@inferred intern(String, split("aa bb cc")[1])
3240
end
3341
end
3442

43+
@testset "WeakRefString" begin
44+
using WeakRefStrings
45+
s1 = "ex"
46+
s2 = "ex"
47+
ex1 = @inferred intern(String, WeakRefString(Vector{UInt8}(s1)))
48+
@test ex1=="ex"
49+
@test !(ex1===s1)
50+
@test ex1 isa String
51+
ex2 = @inferred intern(String, WeakRefString(Vector{UInt8}(s2)))
52+
@test ex1===ex2
53+
end
54+
3555
#== Uncomment when https://github.com/JuliaLang/julia/issues/26939 is fixed
3656
@testset "BigFloat" begin let
3757
pi1 = intern(BigFloat(π))

0 commit comments

Comments
 (0)