Skip to content

Commit 01ecdd8

Browse files
committed
added test
1 parent 62131c2 commit 01ecdd8

File tree

8 files changed

+113
-193
lines changed

8 files changed

+113
-193
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66

77
*.png
88
!readme_string_sort.png
9+
Manifest.toml

Manifest.toml

-118
This file was deleted.

Project.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
name = "ShortStrings"
22
uuid = "63221d1c-8677-4ff0-9126-0ff0817b4975"
33
authors = ["Dai ZJ <[email protected]>"]
4-
version = "0.2.3"
4+
version = "0.2.4"
55

66
[deps]
77
BitIntegers = "c3b6d118-76ef-56ca-8cc7-ebb389d030a1"
88
SortingAlgorithms = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
99

1010
[compat]
11-
SortingAlgorithms = "0.3"
1211
BitIntegers = "0.2"
12+
SortingAlgorithms = "0.3"
1313
julia = "1"
1414

1515
[extras]

benchmarks/hash.jl

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using ShortStrings, BenchmarkTools
2+
3+
# these two should be on par
4+
@benchmark hash($(ShortString{UInt128}("this is a test")), $(zero(UInt)))
5+
@benchmark hash($(rand(UInt128)), $(zero(UInt)))
6+
7+
8+
# faster for some reason
9+
@benchmark hash($"this is a test", $(zero(UInt)))
10+
11+
12+
# these two should be on par
13+
@benchmark hash($(ShortString{UInt128}("this is a test")))
14+
@benchmark hash($(rand(UInt128)))
15+
16+
17+
# faster
18+
@benchmark hash($"this is a test")

src/ShortStrings.jl

+3-73
Original file line numberDiff line numberDiff line change
@@ -6,79 +6,9 @@ export fsort, fsort!, ShortString,
66
ShortString3, ShortString7, ShortString15, ShortString30, ShortString62, ShortString126,
77
@ss3_str, @ss7_str, @ss15_str, @ss30_str, @ss62_str, @ss126_str
88

9-
import Base:unsafe_getindex, ==, show, promote_rule
9+
export hash # from hash.jl
1010

11-
struct ShortString{T} <: AbstractString where T
12-
size_content::T
13-
end
14-
15-
function ShortString{T}(s::Union{String, SubString{String}}) where T
16-
sz = sizeof(s)
17-
max_len = sizeof(T) - size_nibbles(T)
18-
if sz > max_len # the last byte is used to store the length
19-
throw(ErrorException("sizeof(::ShortString) must be shorter than or equal to $(max_len) in length; you have supplied a string of size $sz"))
20-
end
21-
bits_to_wipe = 8(sizeof(T) - sz)
22-
content = (T(s |> pointer |> Ptr{T} |> Base.unsafe_load |> ntoh) >> bits_to_wipe) << bits_to_wipe
23-
ShortString{T}(content | T(sz))
24-
end
25-
26-
String(s::ShortString) = String(reinterpret(UInt8, [s.size_content|>ntoh])[1:sizeof(s)])
27-
28-
Base.codeunit(s::ShortString) = codeunit(String(s))
29-
Base.codeunit(s::ShortString, i) = codeunits(String(s), i)
30-
Base.codeunit(s::ShortString, i::Integer) = codeunit(String(s), i)
31-
Base.codeunits(s::ShortString) = codeunits(String(s))
32-
Base.convert(::ShortString{T}, s::String) where T = ShortString{T}(s)
33-
Base.convert(::String, ss::ShortString) = String(a) #reduce(*, ss)
34-
Base.display(s::ShortString) = display(String(s))
35-
Base.firstindex(::ShortString) = 1
36-
Base.isvalid(s::ShortString, i::Integer) = isvalid(String(s), i)
37-
Base.iterate(s::ShortString) = iterate(String(s))
38-
Base.iterate(s::ShortString, i::Integer) = iterate(String(s), i)
39-
Base.lastindex(s::ShortString) = sizeof(s)
40-
Base.ncodeunits(s::ShortString) = ncodeunits(String(s))
41-
Base.print(s::ShortString) = print(String(s))
42-
Base.show(io::IO, str::ShortString) = show(io, String(str))
43-
Base.sizeof(s::ShortString{T}) where T = Int(s.size_content & size_mask(T))
44-
45-
size_nibbles(::Type{<:Union{UInt16, UInt32, UInt64, UInt128}}) = 1
46-
size_nibbles(::Type{<:Union{Int16, Int32, Int64, Int128}}) = 1
47-
size_nibbles(::Type{<:Union{UInt256, UInt512, UInt1024}}) = 2
48-
size_nibbles(::Type{<:Union{Int256, Int512, Int1024}}) = 2
49-
size_nibbles(::Type{T}) where T = ceil(log2(sizeof(T))/4)
50-
51-
size_mask(T) = UInt(exp2(4*size_nibbles(T)) - 1)
52-
53-
54-
Base.getindex(s::ShortString{T}, i::Integer) where T = begin
55-
Char((s.size_content << 8(i-1)) >> 8(sizeof(T)-1))
56-
end
57-
Base.collect(s::ShortString) = getindex.(s, 1:lastindex(s))
58-
59-
==(s::ShortString, b::String) = begin
60-
String(s) == b
61-
end
62-
63-
promote_rule(::Type{String}, ::Type{ShortString{S}}) where S = String
64-
promote_rule(::Type{ShortString{T}}, ::Type{ShortString{S}}) where {T,S} = ShortString{promote_rule(T,S)}
65-
66-
size_content(s::ShortString) = s.size_content
67-
68-
for T in (UInt1024, UInt512, UInt256, UInt128, UInt64, UInt32)
69-
max_len = sizeof(T) - size_nibbles(T)
70-
constructor_name = Symbol(:ShortString, max_len)
71-
macro_name = Symbol(:ss, max_len, :_str)
72-
73-
@eval const $constructor_name = ShortString{$T}
74-
@eval macro $(macro_name)(s)
75-
Expr(:call, $constructor_name, s)
76-
end
77-
end
78-
79-
fsort(v::Vector{ShortString{T}}; rev = false) where T = sort(v, rev = rev, by = size_content, alg = RadixSort)
80-
fsort!(v::Vector{ShortString{T}}; rev = false) where T = sort!(v, rev = rev, by = size_content, alg = RadixSort)
81-
82-
fsortperm(v::Vector{ShortString{T}}; rev = false) where T = sortperm(v, rev = rev)
11+
include("base.jl")
12+
include("hash.jl")
8313

8414
end # module

src/base.jl

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# this is for keeping the basic functionalities
2+
3+
import Base:unsafe_getindex, ==, show, promote_rule
4+
5+
struct ShortString{T} <: AbstractString where T
6+
size_content::T
7+
end
8+
9+
10+
function ShortString{T}(s::Union{String, SubString{String}}) where T
11+
sz = sizeof(s)
12+
max_len = sizeof(T) - size_nibbles(T)
13+
if sz > max_len # the last byte is used to store the length
14+
throw(ErrorException("sizeof(::ShortString) must be shorter than or equal to $(max_len) in length; you have supplied a string of size $sz"))
15+
end
16+
bits_to_wipe = 8(sizeof(T) - sz)
17+
content = (T(s |> pointer |> Ptr{T} |> Base.unsafe_load |> ntoh) >> bits_to_wipe) << bits_to_wipe
18+
ShortString{T}(content | T(sz))
19+
end
20+
21+
String(s::ShortString) = String(reinterpret(UInt8, [s.size_content|>ntoh])[1:sizeof(s)])
22+
23+
Base.codeunit(s::ShortString) = codeunit(String(s))
24+
Base.codeunit(s::ShortString, i) = codeunits(String(s), i)
25+
Base.codeunit(s::ShortString, i::Integer) = codeunit(String(s), i)
26+
Base.codeunits(s::ShortString) = codeunits(String(s))
27+
Base.convert(::ShortString{T}, s::String) where T = ShortString{T}(s)
28+
Base.convert(::String, ss::ShortString) = String(a) #reduce(*, ss)
29+
Base.display(s::ShortString) = display(String(s))
30+
Base.firstindex(::ShortString) = 1
31+
Base.isvalid(s::ShortString, i::Integer) = isvalid(String(s), i)
32+
Base.iterate(s::ShortString) = iterate(String(s))
33+
Base.iterate(s::ShortString, i::Integer) = iterate(String(s), i)
34+
Base.lastindex(s::ShortString) = sizeof(s)
35+
Base.ncodeunits(s::ShortString) = ncodeunits(String(s))
36+
Base.print(s::ShortString) = print(String(s))
37+
Base.show(io::IO, str::ShortString) = show(io, String(str))
38+
Base.sizeof(s::ShortString{T}) where T = Int(s.size_content & size_mask(T))
39+
40+
size_nibbles(::Type{<:Union{UInt16, UInt32, UInt64, UInt128}}) = 1
41+
size_nibbles(::Type{<:Union{Int16, Int32, Int64, Int128}}) = 1
42+
size_nibbles(::Type{<:Union{UInt256, UInt512, UInt1024}}) = 2
43+
size_nibbles(::Type{<:Union{Int256, Int512, Int1024}}) = 2
44+
size_nibbles(::Type{T}) where T = ceil(log2(sizeof(T))/4)
45+
46+
size_mask(T) = UInt(exp2(4*size_nibbles(T)) - 1)
47+
48+
49+
Base.getindex(s::ShortString{T}, i::Integer) where T = begin
50+
Char((s.size_content << 8(i-1)) >> 8(sizeof(T)-1))
51+
end
52+
Base.collect(s::ShortString) = getindex.(s, 1:lastindex(s))
53+
54+
==(s::ShortString, b::String) = begin
55+
String(s) == b
56+
end
57+
58+
promote_rule(::Type{String}, ::Type{ShortString{S}}) where S = String
59+
promote_rule(::Type{ShortString{T}}, ::Type{ShortString{S}}) where {T,S} = ShortString{promote_rule(T,S)}
60+
61+
size_content(s::ShortString) = s.size_content
62+
63+
for T in (UInt1024, UInt512, UInt256, UInt128, UInt64, UInt32)
64+
max_len = sizeof(T) - size_nibbles(T)
65+
constructor_name = Symbol(:ShortString, max_len)
66+
macro_name = Symbol(:ss, max_len, :_str)
67+
68+
@eval const $constructor_name = ShortString{$T}
69+
@eval macro $(macro_name)(s)
70+
Expr(:call, $constructor_name, s)
71+
end
72+
end
73+
74+
fsort(v::Vector{ShortString{T}}; rev = false) where T = sort(v, rev = rev, by = size_content, alg = RadixSort)
75+
fsort!(v::Vector{ShortString{T}}; rev = false) where T = sort!(v, rev = rev, by = size_content, alg = RadixSort)
76+
77+
fsortperm(v::Vector{ShortString{T}}; rev = false) where T = sortperm(v, rev = rev)

src/hash.jl

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export hash
2+
3+
import Base.hash
4+
5+
Base.hash(x::ShortString, args...; kwargs...) = hash(x.size_content, args...; kwargs...)
6+
7+
Base.hash(x::ShortString, h::UInt) = hash(x.size_content, h)

test/hash.jl

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using ShortStrings: ShortString, hash
2+
using Test
3+
4+
5+
@test ShortString(10) == hash(UInt(10))

0 commit comments

Comments
 (0)