No matching definitions.

cstr

stdlib/cstr.tur

byte primitives on raw :cstr values.

Small pure-Turmeric surface for reading the length of a NUL-terminated C string and the byte at a given index. Sits below stdlib/str.tur, which wraps a :cstr in a length-tagged view struct. Use these when you just want to walk a literal like "1+2*(3+4)" byte by byte without allocating a view.

Not autoloaded: (import cstr :refer [cstr-len cstr-nth]) explicitly. See docs/archive/history/no-cstr-byte-primitives-pure-turmeric.md for why (an earlier attempt to autoload perturbed Vec element-type inference).

Since: 2026-07-01

defn

cstr-len

(cstr-len [s :cstr] :int)

byte length of a NUL-terminated C string.

sNUL-terminated C string pointer

Length in bytes, excluding the trailing NUL.

(cstr-len "hello")  ; => 5
defn

cstr-nth

(cstr-nth [s :cstr i :int] :int)

byte at index i in a NUL-terminated C string.

sNUL-terminated C string pointer
izero-based byte index; caller must ensure 0 <= i < (cstr-len s)

The unsigned byte value at position i.

(cstr-nth "1+2" 1)  ; => 43  ('+')
defn

cstr-byte-is?

(cstr-byte-is? [s :cstr i :int c :Char] :bool)

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

Unlike cstr-nth this checks the index: it is false when i is negative or at or past the terminator, so a scanner needs no separate length test and no magic numbers. c should be ASCII, as for string/byte-is?. A cstr stores no length, so every call measures s: cheap for a line or a token, but a byte-by-byte walk over a long text should make it a String once and use string/byte-is?.

sNUL-terminated C string pointer
ia byte index; out of range is not an error
cthe character to compare with

true iff 0 <= i < (cstr-len s) and the byte at i is c's code.

(cstr-byte-is? "a,b" 1 #\,)  ; => true
(cstr-byte-is? "a,b" 3 #\,)  ; => false

Since: markdown-library-plan S1

defn

cstr-char-at

(cstr-char-at [s :cstr i :int] :(Option Char))

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

The checked counterpart of cstr-nth, for comparing with character literals. Measures s on every call, like cstr-byte-is?.

sNUL-terminated C string pointer
ia byte index; out of range is not an error

(some c) holding the byte at i, or (none) when i is negative or at or past the terminator.

(cstr-char-at "hi" 1)  ; => (some #\i)

Since: markdown-library-plan S1

defn

cstr-starts-with?

(cstr-starts-with? [s :cstr prefix :cstr] :bool)

true iff s begins with prefix.

sNUL-terminated C string pointer
prefixNUL-terminated C string pointer

true iff the first (cstr-len prefix) bytes of s are prefix's. Every string starts with "".

(cstr-starts-with? "# Title" "# ")  ; => true

Since: markdown-library-plan S2

defn

cstr-ends-with?

(cstr-ends-with? [s :cstr suffix :cstr] :bool)

true iff s ends with suffix.

sNUL-terminated C string pointer
suffixNUL-terminated C string pointer

true iff the last (cstr-len suffix) bytes of s are suffix's. Every string ends with "".

(cstr-ends-with? "guide.md" ".md")  ; => true

Since: markdown-library-plan S2

defn

cstr-index-of

(cstr-index-of [s :cstr needle :cstr] :(Option int))

byte offset of the first occurrence of needle in s.

sNUL-terminated C string pointer to search
needleNUL-terminated C string pointer to find

(some i) for the lowest i where needle occurs, or (none). The empty needle is found at 0.

(cstr-index-of "key: value" ": ")  ; => (some 3)

Since: markdown-library-plan S2

defn

cstr-index-of-char

(cstr-index-of-char [s :cstr c :Char] :(Option int))

byte offset of the first c in s.

sNUL-terminated C string pointer to search
cthe character to find (ASCII; see cstr-byte-is?)

(some i) for the lowest i holding c, or (none). The terminator is not searched, so a NUL byte is never found.

(cstr-index-of-char "a=b" #\=)  ; => (some 1)

Since: markdown-library-plan S2

defn

cstr-span-while

(cstr-span-while [s :cstr start :int pred :(fn [Char] bool)] :int)

the index where a run of bytes satisfying pred ends.

string/span-while for a cstr: scans from start while pred holds.

sNUL-terminated C string pointer to scan
startthe byte offset to start at (clamped into [0, (cstr-len s)])
predthe test each byte must pass to continue the run

The end of the run: an index in [start, (cstr-len s)].

(cstr-span-while "  - item" 0 space?)  ; => 2

Since: markdown-library-plan S2

defn

cstr-sub

(cstr-sub [s :cstr start :int end :int] :cstr)

substring [start, end) of a NUL-terminated C string.

sNUL-terminated C string pointer
startzero-based start byte index (clamped into [0, len])
endexclusive end byte index (clamped into [start, len])

A freshly heap-allocated cstr holding the bytes of s in [start, end), NUL-terminated. Out-of-range indices are clamped, so the result is always a valid (possibly empty) string. The caller frees the result.

(cstr-sub "hello" 1 4)  ; => "ell"
defn

cstr-eq?

(cstr-eq? [a :cstr b :cstr] :bool)

content equality on two NUL-terminated C strings.

The = operator has no cstr overload at all (comparing two cstr values with it is a TUR-E0006 operator-lookup error), so a byte-wise comparison needs a named function. (eq? a b) from the auto-loaded Eq[cstr] instance is the same comparison reached through typeclass dispatch; this is the direct call, for code that walks bytes with the rest of this module and does not otherwise want typeclass machinery.

aNUL-terminated C string pointer, or NULL
bNUL-terminated C string pointer, or NULL

true when both are NULL, or both are non-NULL and hold the same bytes up to the terminator. false otherwise -- in particular a NULL never equals a non-NULL, including the empty string.

(cstr-eq? "abc" (cstr-sub "abcdef" 0 3))  ; => true
(cstr-eq? "abc" "abd")                    ; => false
defn

cstr-free

(cstr-free [s :cstr] :void)

release a cstr this module heap-allocated.

cstr-sub hands back a malloc'd string and documents that the caller frees it, but drop! wants a ref<T> and rejects a bare cstr, so without this there is no way to honor that contract from Turmeric -- every caller had to drop into inline C. Pass only a pointer this module allocated: a string literal is static, and freeing one is undefined. NULL is accepted and ignored, matching free(3).

sa cstr returned by cstr-sub, or NULL
(let [t (cstr-sub "hello world" 0 5)]
  (println t)
  (cstr-free t))
Internal definitions
cstr-match-at-- internal: do bytes [k, n) of p equal s's from at+k on?
cstr-index-of-loop-- internal: first match of needle (length m) at i..last.
cstr-index-of-byte-loop-- internal: first i in [i, n) holding byte b.
cstr-span-loop-- internal: first i in [i, n) whose byte fails pred, else n.