No matching definitions.

tur/string-slice

stdlib/string-slice.tur

StringSlice: a zero-copy, bounds-checked view into a String.

A StringSlice is a { parent String; offset; len } view that RETAINS its parent String. Because String is immutable and refcounted, the borrowed byte range stays valid and unchanging for the slice's lifetime -- so this is genuinely safe zero-copy ranged access, unlike a raw pointer+len view over a cstr whose backing buffer can be freed or mutated underneath it.

Sub-slicing (slice/sub) is O(1): a new view over the same parent. Indexing (slice/byte-at) is bounds-checked (returns -1 out of range). Materialize to an owned String (slice/to-string) or a fresh cstr (slice/to-cstr) only at the boundary where you need one.

This supersedes the inert borrowed-view str (stdlib/str.tur) for the safe, owned case: prefer a String + StringSlice when the view must not outlive -- or be invalidated by -- its source. str remains for zero-ownership interop over a caller-managed buffer.

Every op has an interpreter native (src/turi/string_native.c), so StringSlice behaves identically compiled and under --interpret.

Since: v2 (owned-string-type-plan -- String slices)

defopaque

StringSlice

(defopaque StringSlice :ptr<void>)
defn

string/slice

(string/slice [s :String off :int len :int] :StringSlice)

a zero-copy view of String s over bytes [off, off+len).

The slice retains s, so the range stays valid until the slice is released. off/len are clamped to s's bounds, so the result is always a valid view.

sthe parent String (retained by the slice)
offstart byte offset (clamped into [0, len s])
lennumber of bytes (clamped so off+len <= len s)

A StringSlice viewing the requested range.

(slice/to-cstr (string/slice (string/from-cstr "hello world") 6 5))  ; => "world"

Since: v2

defn

string/slice-cstr

(string/slice-cstr [s :cstr off :int len :int] :StringSlice)

slice a raw cstr safely by copying it into an owned String the slice solely owns (freed when the slice is released).

Use this to get safe ranged access to a cstr without worrying about the cstr's lifetime: the bytes are copied once, and the copy lives exactly as long as the slice (and its sub-slices).

Since: v2

defn

slice/retain

(slice/retain [sl :StringSlice] :StringSlice)

increment the slice's refcount, returning a second handle.

Since: v2

defn

slice/release

(slice/release [sl :StringSlice] :void)

decrement the slice's refcount; at zero, release the parent.

Since: v2

defn

slice/len

(slice/len [sl :StringSlice] :int)

byte length of the slice.

Since: v2

defn

slice/empty?

(slice/empty? [sl :StringSlice] :bool)

true iff the slice has length zero.

Since: v2

defn

slice/byte-at

(slice/byte-at [sl :StringSlice i :int] :int)

the byte (0..255) at index i, or -1 if out of range.

Since: v2

defn

slice/byte-is?

(slice/byte-is? [sl :StringSlice i :int c :Char] :bool)

is the byte at index i of the slice the character c?

string/byte-is? for a slice. The index is relative to the slice, and so is the bounds check: a byte of the parent String outside the view is out of range. c should be ASCII, as for string/byte-is?.

slthe slice to look in (borrowed)
ia byte index into the slice; out of range is not an error
cthe character to compare with

true iff 0 <= i < (slice/len sl) and the byte at i is c's code.

(slice/byte-is? (string/slice (string/from-cstr "a,b") 1 2) 0 #\,)  ; => true

Since: markdown-library-plan S1

defn

slice/char-at

(slice/char-at [sl :StringSlice i :int] :(Option Char))

the byte at index i of the slice as a Char, or (none).

string/char-at for a slice; the index and the bounds are the slice's.

slthe slice to look in (borrowed)
ia byte index into the slice; out of range is not an error

(some c) holding the byte at i, or (none) when i is out of range.

(slice/char-at (string/slice (string/from-cstr "hi") 1 1) 0)  ; => (some #\i)

Since: markdown-library-plan S1

defn

slice/-match-at

(slice/-match-at [sl :StringSlice p :String at :int k :int n :int] :bool)

internal: do bytes [k, n) of p equal sl's from at+k on?

defn

slice/starts-with-at?

(slice/starts-with-at? [sl :StringSlice prefix :String at :int] :bool)

does prefix occur in the slice at byte offset at?

string/starts-with-at? for a slice.

slthe slice to look in (borrowed)
prefixthe bytes to look for (borrowed)
atthe byte offset in the slice to test

true iff the slice's bytes from at on begin with prefix.

(slice/starts-with-at? (string/slice (string/from-cstr "x <!-- y") 2 6) (string/from-cstr "<!--") 0)  ; => true

Since: markdown-library-plan S2

defn

slice/-index-of-loop

(slice/-index-of-loop [sl :StringSlice needle :String i :int last :int] :(Option int))

internal: first match of needle at i..last.

defn

slice/index-of-from

(slice/index-of-from [sl :StringSlice needle :String start :int] :(Option int))

offset of the first needle at or after start.

string/index-of-from for a slice.

slthe slice to search (borrowed)
needlethe bytes to find (borrowed)
startthe first slice offset a match may begin at

(some i) for the lowest i >= start where needle occurs, else (none).

(slice/index-of-from (string/slice (string/from-cstr "a,b,c") 0 5) (string/from-cstr ",") 2)  ; => (some 3)

Since: markdown-library-plan S2

defn

slice/index-of

(slice/index-of [sl :StringSlice needle :String] :(Option int))

offset of the first occurrence of needle in the slice.

string/index-of for a slice.

slthe slice to search (borrowed)
needlethe bytes to find (borrowed)

(some i) for the lowest i where needle occurs, or (none).

(slice/index-of (string/slice (string/from-cstr "<p>a</p>") 3 5) (string/from-cstr "</"))  ; => (some 1)

Since: markdown-library-plan S2

defn

slice/-last-index-of-loop

(slice/-last-index-of-loop [sl :StringSlice needle :String i :int] :(Option int))

internal: last match of needle at i down to 0.

defn

slice/last-index-of

(slice/last-index-of [sl :StringSlice needle :String] :(Option int))

offset of the last occurrence of needle in the slice.

string/last-index-of for a slice.

slthe slice to search (borrowed)
needlethe bytes to find (borrowed)

(some i) for the highest i where needle occurs, or (none).

(slice/last-index-of (string/slice (string/from-cstr "a/b/c/") 0 5) (string/from-cstr "/"))  ; => (some 3)

Since: markdown-library-plan S2

defn

slice/-index-of-byte-loop

(slice/-index-of-byte-loop [sl :StringSlice b :int i :int n :int] :(Option int))

internal: first i in [i, n) holding byte b.

defn

slice/index-of-char-from

(slice/index-of-char-from [sl :StringSlice c :Char start :int] :(Option int))

offset of the first c at or after start.

string/index-of-char-from for a slice.

slthe slice to search (borrowed)
cthe character to find (ASCII)
startthe first slice offset to look at

(some i) for the lowest i >= start holding c, or (none).

(slice/index-of-char-from (string/slice (string/from-cstr "a]b]") 0 4) #\] 2)  ; => (some 3)

Since: markdown-library-plan S2

defn

slice/index-of-char

(slice/index-of-char [sl :StringSlice c :Char] :(Option int))

offset of the first c in the slice.

string/index-of-char for a slice.

slthe slice to search (borrowed)
cthe character to find (ASCII)

(some i) for the lowest i holding c, or (none).

(slice/index-of-char (string/slice (string/from-cstr "x [a] y") 2 3) #\])  ; => (some 2)

Since: markdown-library-plan S2

defn

slice/-span-loop

(slice/-span-loop [sl :StringSlice pred :(fn [Char] bool) i :int n :int] :int)

internal: first i in [i, n) whose byte fails pred, else n.

defn

slice/span-while

(slice/span-while [sl :StringSlice start :int pred :(fn [Char] bool)] :int)

the slice index where a run satisfying pred ends.

string/span-while for a slice: the run stops at the slice's end, not its parent's.

slthe slice to scan (borrowed)
startthe slice offset to start at (clamped into [0, (slice/len sl)])
predthe test each byte must pass to continue the run

The end of the run: an index in [start, (slice/len sl)].

(slice/span-while (string/slice (string/from-cstr "x  abc") 1 5) 0 space?)  ; => 2

Since: markdown-library-plan S2

defn

slice/-run-loop

(slice/-run-loop [sl :StringSlice b :int i :int n :int] :int)

internal: first i in [i, n) not holding byte b, else n.

defn

slice/run-length

(slice/run-length [sl :StringSlice start :int c :Char] :int)

how many c in a row start at start in the slice.

string/run-length for a slice: the run stops at the slice's end.

slthe slice to scan (borrowed)
startthe slice offset the run starts at
cthe character the run is made of (ASCII)

The run's length in bytes, 0 or more.

(slice/run-length (string/slice (string/from-cstr "````x") 0 3) 0 #\`)  ; => 3

Since: markdown-library-plan S2

defn

slice/-new-vec

(slice/-new-vec :(Vec StringSlice))

internal: an empty (Vec StringSlice) (a let-bound vec-new is not inferred).

defn

string/-line-slices-loop

(string/-line-slices-loop [s :String out :(Vec StringSlice) start :int i :int n :int] :(Vec StringSlice))

internal: push views of s's lines from start into out.

defn

string/line-slices

(string/line-slices [s :String] :(Vec StringSlice))

zero-copy views of s's lines, without their endings.

string/lines without the copies: the same LF / CRLF / CR rule, the same lines, but each is a StringSlice viewing s. This is the form a parser wants for its input: one String for the document, one O(1) view per line.

sthe String to split (borrowed; each slice retains it)

A fresh (Vec StringSlice), possibly empty. Free it with slice/release-all.

(vec-len (string/line-slices (string/from-cstr "# Title\n\nBody\n")))  ; => 3

Since: markdown-library-plan S3

defn

slice/-split-char-loop

(slice/-split-char-loop [sl :StringSlice c :Char out :(Vec StringSlice) start :int] :(Vec StringSlice))

internal: split sl on c from start into out.

defn

slice/split-char

(slice/split-char [sl :StringSlice c :Char] :(Vec StringSlice))

zero-copy views of the parts of sl between each c.

string/split-char for a slice, without the copies: empty parts are kept, and each part is a sub-slice of sl over the same parent String. A table row's cells, for instance.

slthe slice to split (borrowed; each part retains its parent)
cthe separator character (ASCII)

A fresh (Vec StringSlice), at least one part. Free it with slice/release-all.

(vec-len (slice/split-char (string/slice (string/from-cstr "|a|b|") 0 5) #\|))  ; => 4

Since: markdown-library-plan S3

defn

slice/-release-loop

(slice/-release-loop [v :(Vec StringSlice) i :int n :int] :void)

internal: release v's elements [i, n).

defn

slice/release-all

(slice/release-all [v :(Vec StringSlice)] :void)

release every StringSlice in v, then free v itself.

The one call that frees what string/line-slices and slice/split-char return. Releasing the last slice over a String releases that String's reference too.

va (Vec StringSlice) whose elements this call owns
(slice/release-all (string/line-slices (string/from-cstr "a\nb")))

Since: markdown-library-plan S3

defn

slice/-trim-end-loop

(slice/-trim-end-loop [sl :StringSlice lo :int i :int] :int)

internal: the index past the last non-space byte in [lo, i).

defn

slice/trim

(slice/trim [sl :StringSlice] :StringSlice)

a view of sl without its leading and trailing ASCII whitespace.

string/trim without the copy. Whitespace is char.tur's space?, the set string/trim strips. An all-whitespace slice gives an empty one.

slthe slice to trim (borrowed)

A fresh StringSlice over the same parent; release it with slice/release.

(slice/to-cstr (slice/trim (string/slice (string/from-cstr "| a b |") 1 5)))  ; => "a b"

Since: markdown-library-plan S4

defn

slice/trim-start

(slice/trim-start [sl :StringSlice] :StringSlice)

a view of sl without its leading ASCII whitespace.

slthe slice to trim (borrowed)

A fresh StringSlice over the same parent; release it with slice/release.

(slice/to-cstr (slice/trim-start (string/slice (string/from-cstr "   code") 0 7)))  ; => "code"

Since: markdown-library-plan S4

defn

slice/trim-end

(slice/trim-end [sl :StringSlice] :StringSlice)

a view of sl without its trailing ASCII whitespace.

slthe slice to trim (borrowed)

A fresh StringSlice over the same parent; release it with slice/release.

(slice/to-cstr (slice/trim-end (string/slice (string/from-cstr "# Hi  ") 0 6)))  ; => "# Hi"

Since: markdown-library-plan S4

defn

slice/-parse-digits

(slice/-parse-digits [sl :StringSlice i :int n :int acc :int] :(Option int))

internal: string/-parse-digits for a slice.

defn

slice/parse-int

(slice/parse-int [sl :StringSlice] :(Option int))

the decimal integer sl spells, or (none).

string/parse-int for a slice, with no copy: an optional + or -, then one or more digits, and nothing else in the slice. Out of the 64-bit int range is (none). An ordered list item's start number, sliced out of its line, parses straight from the view.

slthe slice to parse (borrowed)

(some n) when sl is exactly a decimal integer n, else (none).

(slice/parse-int (string/slice (string/from-cstr "12. item") 0 2))  ; => (some 12)

Since: markdown-library-plan S4

defn

slice/compare

(slice/compare [a :StringSlice b :StringSlice] :int)

lexicographic byte compare of two slices: -1, 0, or 1.

Since: v2

defn

slice/eq?

(slice/eq? [a :StringSlice b :StringSlice] :bool)

content equality of two slices.

Since: v2

defn

slice/hash

(slice/hash [sl :StringSlice] :int)

content hash over the slice's byte range.

Since: v2

defn

slice/sub

(slice/sub [sl :StringSlice off :int len :int] :StringSlice)

a sub-view [off, off+len) RELATIVE to this slice (clamped).

O(1): the result views the same parent String; no bytes are copied.

(let [w (string/slice (string/from-cstr "hello world") 6 5)]  ; "world"
  (slice/to-cstr (slice/sub w 0 3)))                          ; => "wor"

Since: v2

defn

builder/push-slice!

(builder/push-slice! [b :StringBuilder sl :StringSlice] :void)

append a slice's bytes to the builder.

Copies the viewed range straight from the parent String, so a parser can assemble output from views of its input without a slice/to-string temporary for each. The slice is borrowed, not released.

bthe builder to append to
slthe slice whose bytes to append (borrowed)
(let [b (builder/new)]
  (do (builder/push-slice! b (string/slice (string/from-cstr "hello world") 6 5))
      (string/to-cstr (builder/finish b))))  ; => "world"

Since: markdown-library-plan S5

definstance

BuilderPush[StringSlice]

(definstance BuilderPush [StringSlice])

the viewed bytes, as builder/push-slice!.

defn

slice/to-string

(slice/to-string [sl :StringSlice] :String)

copy the slice's range into a fresh owned String.

Since: v2

defn

slice/to-cstr

(slice/to-cstr [sl :StringSlice] :cstr)

copy the slice's range into a fresh NUL-terminated cstr.

The result is a freshly heap-allocated cstr (the caller frees it, or adopts it with string/adopt-cstr). A slice is not NUL-terminated at its end, so there is deliberately no borrowed cstr view -- this always copies.

Since: v2

definstance

Eq[StringSlice]

(definstance Eq [StringSlice])

content equality (no allocation).

definstance

Ord[StringSlice]

(definstance Ord [StringSlice])

lexicographic byte ordering.

definstance

Show[StringSlice]

(definstance Show [StringSlice])

the slice content as a fresh owned String. slice/to-cstr always mallocs, so adopting it is leak-free.

definstance

Hash[StringSlice]

(definstance Hash [StringSlice])

content hash over the byte range.