Files
nt-lite/code/public/ntlite/string_view.h
T

226 lines
7.8 KiB
C

// Public NTLite string view ABI declarations shared between kernel, drivers, and user mode.
#pragma once
// sys_string.h - shared native string-view ABI.
// A SYS_STRING_VIEW is a borrowed byte span. Length counts bytes, never Unicode
// scalar values or characters. The view is not NUL-terminated and owns no storage.
// Native names/text must contain strict UTF-8 (no normalization or case folding);
// generic byte payloads may use the same representation without becoming text.
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#ifndef SYS_STRING_VIEW_DEFINED
#define SYS_STRING_VIEW_DEFINED 1
typedef struct SYS_STRING_VIEW {
const char* Data;
size_t Length;
} SYS_STRING_VIEW;
#endif
#define SYS_SV_LITERAL(s) ((SYS_STRING_VIEW){ (s), sizeof(s) - 1 })
#define SYS_SV_NULL ((SYS_STRING_VIEW){ (const char*)0, 0 })
// Implements the sv From Parts operation.
static inline SYS_STRING_VIEW SysSvFromParts(const char* data, size_t length) {
SYS_STRING_VIEW v;
v.Data = data;
v.Length = length;
return v;
}
// Implements the sv From Cstr operation.
static inline SYS_STRING_VIEW SysSvFromCstr(const char* s) {
SYS_STRING_VIEW v;
v.Data = s;
v.Length = s ? strlen(s) : 0;
return v;
}
// Implements the sv Is Empty operation.
static inline bool SysSvIsEmpty(SYS_STRING_VIEW s) {
return s.Length == 0;
}
// Implements the sv Is Valid operation.
static inline bool SysSvIsValid(SYS_STRING_VIEW s) {
return s.Data != (const char*)0 || s.Length == 0;
}
// Validates well-formed UTF-8 bytes (RFC 3629). No normalization is performed.
// Rejects overlong encodings, surrogates, truncated sequences and > U+10FFFF.
static inline bool SysSvIsUtf8(SYS_STRING_VIEW view) {
if (!SysSvIsValid(view)) return false;
const uint8_t* data = (const uint8_t*)view.Data;
size_t i = 0;
while (i < view.Length) {
uint8_t lead = data[i++];
if (lead <= 0x7Fu) continue;
uint32_t scalar;
size_t continuation;
if (lead >= 0xC2u && lead <= 0xDFu) {
scalar = lead & 0x1Fu;
continuation = 1;
} else if (lead >= 0xE0u && lead <= 0xEFu) {
scalar = lead & 0x0Fu;
continuation = 2;
} else if (lead >= 0xF0u && lead <= 0xF4u) {
scalar = lead & 0x07u;
continuation = 3;
} else {
return false;
}
if (continuation > view.Length - i) return false;
for (size_t j = 0; j < continuation; ++j) {
uint8_t byte = data[i++];
if ((byte & 0xC0u) != 0x80u) return false;
scalar = (scalar << 6) | (uint32_t)(byte & 0x3Fu);
}
if ((continuation == 1 && scalar < 0x80u) ||
(continuation == 2 && scalar < 0x800u) ||
(continuation == 3 && scalar < 0x10000u) ||
(scalar >= 0xD800u && scalar <= 0xDFFFu) || scalar > 0x10FFFFu)
return false;
}
return true;
}
// Names and other retained native text forbid embedded NUL as well as bad UTF-8.
// Empty views, including the canonical null view, are valid text.
static inline bool SysSvIsUtf8Text(SYS_STRING_VIEW view) {
if (!SysSvIsUtf8(view)) return false;
for (size_t i = 0; i < view.Length; ++i)
if (view.Data[i] == '\0') return false;
return true;
}
// Copies external filename bytes into display-only UTF-8, replacing each invalid
// byte (including embedded NUL) with U+FFFD. Never splits a valid scalar or a
// replacement at the output capacity; always NUL-terminates when capacity > 0.
// This is a lossy display projection, not a native namespace identity mapping.
static inline size_t SysSvCopyUtf8WithReplacement(SYS_STRING_VIEW source,
char* destination,
size_t capacity) {
if (!destination || capacity == 0) return 0;
size_t read = 0;
size_t written = 0;
if (!SysSvIsValid(source)) {
destination[0] = '\0';
return 0;
}
while (read < source.Length) {
uint8_t first = (uint8_t)source.Data[read];
size_t sequenceLength = 0;
if (first >= 1u && first <= 0x7Fu) {
sequenceLength = 1;
} else if (first >= 0xC2u && first <= 0xDFu) {
sequenceLength = 2;
} else if (first >= 0xE0u && first <= 0xEFu) {
sequenceLength = 3;
} else if (first >= 0xF0u && first <= 0xF4u) {
sequenceLength = 4;
}
bool valid = sequenceLength && sequenceLength <= source.Length - read &&
SysSvIsUtf8(SysSvFromParts(source.Data + read, sequenceLength));
size_t appendLength = valid ? sequenceLength : 3u;
if (appendLength > capacity - written - 1u) break;
if (valid) {
memcpy(destination + written, source.Data + read, sequenceLength);
read += sequenceLength;
} else {
destination[written] = (char)0xEF;
destination[written + 1u] = (char)0xBF;
destination[written + 2u] = (char)0xBD;
++read;
}
written += appendLength;
}
destination[written] = '\0';
return written;
}
// Implements the sv Equal operation.
static inline bool SysSvEqual(SYS_STRING_VIEW a, SYS_STRING_VIEW b) {
if (a.Length != b.Length) return false;
if (a.Length == 0) return true;
if (!a.Data || !b.Data) return false;
return memcmp(a.Data, b.Data, a.Length) == 0;
}
// Implements the ascii Lower operation.
static inline char SysAsciiLower(char c) {
return (c >= 'A' && c <= 'Z') ? (char)(c + ('a' - 'A')) : c;
}
// Implements the sv Equal Ascii I operation.
static inline bool SysSvEqualAsciiI(SYS_STRING_VIEW a, SYS_STRING_VIEW b) {
if (a.Length != b.Length) return false;
if (a.Length == 0) return true;
if (!a.Data || !b.Data) return false;
for (size_t i = 0; i < a.Length; i++) {
if (SysAsciiLower(a.Data[i]) != SysAsciiLower(b.Data[i])) return false;
}
return true;
}
// Implements the sv Equal Lit operation.
static inline bool SysSvEqualLit(SYS_STRING_VIEW a, const char* lit) {
return SysSvEqual(a, SysSvFromCstr(lit));
}
// Implements the sv Equal Lit Ascii I operation.
static inline bool SysSvEqualLitAsciiI(SYS_STRING_VIEW a, const char* lit) {
return SysSvEqualAsciiI(a, SysSvFromCstr(lit));
}
// Implements the sv Contains Byte operation.
static inline bool SysSvContainsByte(SYS_STRING_VIEW s, char ch) {
if (!s.Data && s.Length) return false;
for (size_t i = 0; i < s.Length; i++) {
if (s.Data[i] == ch) return true;
}
return false;
}
// Implements the sv Slice operation.
static inline SYS_STRING_VIEW SysSvSlice(SYS_STRING_VIEW s, size_t off, size_t len) {
if (off > s.Length) off = s.Length;
if (len > s.Length - off) len = s.Length - off;
return SysSvFromParts(s.Data ? s.Data + off : (const char*)0, len);
}
// Implements the sv Trim Ascii operation.
static inline SYS_STRING_VIEW SysSvTrimAscii(SYS_STRING_VIEW s) {
if (!SysSvIsValid(s)) return SYS_SV_NULL;
size_t begin = 0;
size_t end = s.Length;
while (begin < end) {
char c = s.Data[begin];
if (c != ' ' && c != '\t' && c != '\r' && c != '\n') break;
begin++;
}
while (end > begin) {
char c = s.Data[end - 1];
if (c != ' ' && c != '\t' && c != '\r' && c != '\n') break;
end--;
}
return SysSvSlice(s, begin, end - begin);
}
// Implements the sv Copy Z operation.
static inline bool SysSvCopyZ(char* dst, size_t dstSize, SYS_STRING_VIEW src) {
if (!dst || dstSize == 0) return false;
if (src.Length && !src.Data) return false;
if (src.Length + 1 > dstSize) {
dst[0] = '\0';
return false;
}
if (src.Length) memcpy(dst, src.Data, src.Length);
dst[src.Length] = '\0';
return true;
}