substring
builtins.substring
Primop
Docs pulled from | This Revision | 3 days ago
Nix manual
Takes 3 arguments
start, len, s
Return the substring of s from byte position start
(zero-based) up to but not including start + len. If start is
greater than the length of the string, an empty string is returned.
If start + len lies beyond the end of the string or len is -1,
only the substring up to the end of the string is returned.
start must be non-negative.
For example,
builtins.substring 0 3 "nixos"
evaluates to "nix".
Noogle detected
Detected Type
substring :: Int -> Int -> String -> String
Implementation
This function is implemented in c++ and is part of the native nix runtime.
static void prim_substring(EvalState & state, const PosIdx pos, Value ** args, Value & v)
{
using NixUInt = std::make_unsigned_t<NixInt::Inner>;
NixInt::Inner start =
state
.forceInt(
*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring")
.value;
if (start < 0)
state.error<EvalError>("negative start position in 'substring'").atPos(pos).debugThrow();
NixInt::Inner len =
state
.forceInt(
*args[1],
pos,
"while evaluating the second argument (the substring length) passed to builtins.substring")
.value;
// Negative length may be idiomatically passed to builtins.substring to get
// the tail of the string.
auto _len = std::numeric_limits<std::string::size_type>::max();
// Special-case on empty substring to avoid O(n) strlen
// This allows for the use of empty substrings to efficiently capture string context
if (len == 0) {
state.forceValue(*args[2], pos);
if (args[2]->type() == nString) {
v.mkStringNoCopy(""_sds, args[2]->context());
return;
}
}
if (len >= 0 && NixUInt(len) < _len) {
_len = len;
}
NixStringContext context;
auto s = state.coerceToString(
pos, *args[2], context, "while evaluating the third argument (the string) passed to builtins.substring");
v.mkString(NixUInt(start) >= s->size() ? "" : s->substr(start, _len), context, state.mem);
}