aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/pkg/macos/foundation/string.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/pkg/macos/foundation/string.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/pkg/macos/foundation/string.zig')
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/string.zig174
1 files changed, 174 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/string.zig b/vendor/libghostty-vt/pkg/macos/foundation/string.zig
new file mode 100644
index 00000000..2f679fef
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/string.zig
@@ -0,0 +1,174 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const c = @import("c.zig").c;
+
+pub const String = opaque {
+ pub fn createWithBytes(
+ bs: []const u8,
+ encoding: StringEncoding,
+ external: bool,
+ ) Allocator.Error!*String {
+ return @as(?*String, @ptrFromInt(@intFromPtr(c.CFStringCreateWithBytes(
+ null,
+ bs.ptr,
+ @intCast(bs.len),
+ @intFromEnum(encoding),
+ @intFromBool(external),
+ )))) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createWithCharactersNoCopy(
+ unichars: []const u16,
+ ) *String {
+ return @as(*String, @ptrFromInt(@intFromPtr(c.CFStringCreateWithCharactersNoCopy(
+ null,
+ @ptrCast(unichars.ptr),
+ @intCast(unichars.len),
+ foundation.c.kCFAllocatorNull,
+ ))));
+ }
+
+ pub fn release(self: *String) void {
+ c.CFRelease(self);
+ }
+
+ pub fn getLength(self: *String) usize {
+ return @intCast(c.CFStringGetLength(@ptrCast(self)));
+ }
+
+ pub fn hasPrefix(self: *String, prefix: *String) bool {
+ return c.CFStringHasPrefix(
+ @ptrCast(self),
+ @ptrCast(prefix),
+ ) == 1;
+ }
+
+ pub fn compare(
+ self: *String,
+ other: *String,
+ options: StringComparison,
+ ) foundation.ComparisonResult {
+ return @enumFromInt(c.CFStringCompare(
+ @ptrCast(self),
+ @ptrCast(other),
+ @intCast(@as(c_int, @bitCast(options))),
+ ));
+ }
+
+ pub fn cstring(self: *String, buf: []u8, encoding: StringEncoding) ?[]const u8 {
+ if (c.CFStringGetCString(
+ @ptrCast(self),
+ buf.ptr,
+ @intCast(buf.len),
+ @intFromEnum(encoding),
+ ) == 0) return null;
+ return std.mem.sliceTo(buf, 0);
+ }
+
+ pub fn cstringPtr(self: *String, encoding: StringEncoding) ?[:0]const u8 {
+ const ptr = c.CFStringGetCStringPtr(
+ @ptrCast(self),
+ @intFromEnum(encoding),
+ );
+ if (ptr == null) return null;
+ return std.mem.sliceTo(ptr, 0);
+ }
+};
+
+pub const MutableString = opaque {
+ pub fn create(cap: usize) !*MutableString {
+ return @ptrCast(c.CFStringCreateMutable(
+ null,
+ @intCast(cap),
+ ) orelse return Allocator.Error.OutOfMemory);
+ }
+
+ pub fn release(self: *MutableString) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn string(self: *MutableString) *String {
+ return @ptrCast(self);
+ }
+
+ pub fn appendCharacters(self: *MutableString, chars: []const u16) void {
+ c.CFStringAppendCharacters(
+ @ptrCast(self),
+ chars.ptr,
+ @intCast(chars.len),
+ );
+ }
+};
+
+pub const StringComparison = packed struct {
+ case_insensitive: bool = false,
+ _unused_2: bool = false,
+ backwards: bool = false,
+ anchored: bool = false,
+ nonliteral: bool = false,
+ localized: bool = false,
+ numerically: bool = false,
+ diacritic_insensitive: bool = false,
+ width_insensitive: bool = false,
+ forced_ordering: bool = false,
+ _padding: u22 = 0,
+
+ test {
+ try std.testing.expectEqual(@bitSizeOf(c_int), @bitSizeOf(StringComparison));
+ }
+};
+
+/// https://developer.apple.com/documentation/corefoundation/cfstringencoding?language=objc
+pub const StringEncoding = enum(u32) {
+ invalid = 0xffffffff,
+ mac_roman = 0,
+ windows_latin1 = 0x0500,
+ iso_latin1 = 0x0201,
+ nextstep_latin = 0x0B01,
+ ascii = 0x0600,
+ unicode = 0x0100,
+ utf8 = 0x08000100,
+ non_lossy_ascii = 0x0BFF,
+ utf16_be = 0x10000100,
+ utf16_le = 0x14000100,
+ utf32 = 0x0c000100,
+ utf32_be = 0x18000100,
+ utf32_le = 0x1c000100,
+};
+
+pub fn stringGetSurrogatePairForLongCharacter(
+ ch: u32,
+ surrogates: []u16,
+) bool {
+ assert(surrogates.len >= 2);
+ return c.CFStringGetSurrogatePairForLongCharacter(ch, surrogates.ptr) == 1;
+}
+
+test "string" {
+ const testing = std.testing;
+
+ const str = try String.createWithBytes("hello world", .ascii, false);
+ defer str.release();
+
+ const prefix = try String.createWithBytes("hello", .ascii, false);
+ defer prefix.release();
+
+ try testing.expect(str.hasPrefix(prefix));
+ try testing.expectEqual(foundation.ComparisonResult.equal, str.compare(str, .{}));
+ try testing.expectEqualStrings("hello world", str.cstringPtr(.ascii).?);
+
+ {
+ var buf: [128]u8 = undefined;
+ const cstr = str.cstring(&buf, .ascii).?;
+ try testing.expectEqualStrings("hello world", cstr);
+ }
+}
+
+test "unichar" {
+ const testing = std.testing;
+
+ var unichars: [2]u16 = undefined;
+ try testing.expect(!stringGetSurrogatePairForLongCharacter('A', &unichars));
+}