cstrings.ha (1608B)
1 // License: MPL-2.0 2 // (c) 2021 Drew DeVault <sir@cmpwn.com> 3 // (c) 2021 Ember Sawady <ecs@d2evs.net> 4 // (c) 2022 Vlad-Stefan Harbuz <vlad@vladh.net> 5 use encoding::utf8; 6 use types; 7 8 // Computes the length of a NUL-terminated C string, in octets, in O(n). The 9 // computed length does not include the NUL terminator. 10 export fn cstrlen(cstr: *const char) size = { 11 const ptr = cstr: *[*]u8; 12 let ln = 0z; 13 for (ptr[ln] != 0; ln += 1) void; 14 return ln; 15 }; 16 17 // Converts a C string to a Hare string in O(n), and does not check if it's 18 // valid UTF-8. 19 export fn fromc_unsafe(cstr: *const char) const str = { 20 const l = cstrlen(cstr); 21 const s = types::string { 22 data = cstr: *[*]u8, 23 length = l, 24 capacity = l + 1, 25 }; 26 return *(&s: *const str); 27 }; 28 29 // Converts a C string to a Hare string in O(n). If the string is not valid 30 // UTF-8, return [[encoding::utf8::invalid.]] 31 export fn fromc(cstr: *const char) (const str | utf8::invalid) = { 32 let s = fromc_unsafe(cstr); 33 return if (utf8::valid(s)) s else utf8::invalid; 34 }; 35 36 // Converts a Hare string to a C string. The result is allocated; the caller 37 // must free it when they're done. 38 export fn to_c(s: const str) *char = { 39 let slice: []u8 = alloc([0...], len(s) + 1); 40 return to_cbuf(s, slice); 41 }; 42 43 // Converts a Hare string to a C string. The result is stored into a 44 // user-supplied buffer. 45 export fn to_cbuf(s: const str, sl: []u8) *char = { 46 if (len(sl) < len(s) + 1) { 47 abort("to_cbuf: buffer has insufficient space for string plus NUL"); 48 }; 49 50 const s = &s: *[]u8; 51 sl[..len(s)] = s[..]; 52 sl[len(s)] = 0; 53 54 return (*(&sl: *types::slice)).data: *char; 55 };