Skip to content

Commit 7844a6e

Browse files
authored
add StringView(iobuffer) (#17)
* add StringView(iobuffer) * more restrictive type, more tests
1 parent 881ed12 commit 7844a6e

File tree

4 files changed

+43
-2
lines changed

4 files changed

+43
-2
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "StringViews"
22
uuid = "354b36f9-a18e-4713-926e-db85100087ba"
33
authors = ["Steven G. Johnson <[email protected]>"]
4-
version = "1.2.0"
4+
version = "1.3.0"
55

66
[compat]
77
julia = "1.6"

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ that provides a string representation of any underlying array of bytes
88

99
Unlike Julia's built-in `String` type (which also wraps UTF-8 data), the
1010
`StringView` type is a copy-free wrap of *any* `AbstractVector{UInt8}`
11-
instance, and does not take "ownership" of or modify the array. Otherwise,
11+
instance, and does not take "ownership" of or modify the array.
12+
You can also use `StringView(buf)` with a `buf::IOBuffer`, as
13+
a non-destructive alternative to `String(take!(buf))`. Otherwise,
1214
a `StringView` is intended to be usable in any context where you might
1315
have otherwise used `String`.
1416

@@ -36,6 +38,25 @@ julia> abc = StringView(0x61:0x63) # and for other array types
3638
"abc"
3739
```
3840

41+
Or, with an `IOBuffer`:
42+
43+
```jl
44+
julia> buf = IOBuffer();
45+
46+
julia> write(buf, b);
47+
48+
julia> print(buf, "baz")
49+
50+
julia> StringView(buf) # does not modify buf
51+
"foobarbaz"
52+
53+
julia> String(take!(buf)) # clears buf
54+
"foobarbaz"
55+
56+
julia> StringView(buf) # now empty
57+
""
58+
```
59+
3960
Other optimized (copy-free) operations include I/O, hashing, iteration/indexing,
4061
comparisons, parsing, searching, and validation. Working with a `SubString` of
4162
a `StringView` is similarly efficient.

src/StringViews.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ export StringView, SVRegexMatch
1818
`StringView(array)` creates an `AbstractString` representation of
1919
any `array` of `UInt8` data, interpreted as UTF-8 encoded Unicode.
2020
It does *not* make a copy of or modify `array`.
21+
22+
`StringView(buf::IOBuffer)` returns a string view of the
23+
current contents of the `buf`, equivalent to `String(take!(buf))`
24+
but without making a copy. `StringView(buf::IOBuffer, range)`
25+
is a view of the bytes `range` (defaults to `1:position(buf)-1`)
26+
in the buffer.
2127
"""
2228
struct StringView{T<:AbstractVector{UInt8}} <: AbstractString
2329
data::T
@@ -35,6 +41,10 @@ Base.String(s::StringViewAndSub) = String(copyto!(Base.StringVector(ncodeunits(s
3541
StringView(s::StringView) = s
3642
StringView(s::String) = StringView(codeunits(s))
3743

44+
# iobuffer constructor (note that buf.data is always 1-based)
45+
StringView(buf::IOBuffer, r::OrdinalRange{<:Integer,<:Integer}=Base.OneTo(buf.ptr-1)) =
46+
StringView(@view buf.data[r])
47+
3848
Base.copy(s::StringView) = StringView(copy(s.data))
3949

4050
Base.Symbol(s::DenseStringViewAndSub) =

test/runtests.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ su = StringView("föôẞαr")
2020
@test c == "foobar"
2121
@test c.data !== s.data
2222

23+
buf = IOBuffer()
24+
write(buf, s)
25+
@test StringView(buf) == s == StringView(buf, 0x01:0x06)
26+
@test StringView(buf, 3:5) == "oba" == StringView(buf, 0x03:0x01:0x05)
27+
write(buf, "baz")
28+
@test StringView(buf) == s * "baz"
29+
@test String(take!(buf)) == s * "baz"
30+
@test StringView(buf) == ""
31+
@test_throws BoundsError StringView(buf, 3:4)
32+
2333
@test StringView("foo") isa StringView{Base.CodeUnits{UInt8,String}}
2434

2535
@test s isa StringViews.DenseStringView

0 commit comments

Comments
 (0)