mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-24 00:17:54 +00:00
Add string16 and cstring16 (UTF-16 based strings)
This commit is contained in:
+12
-1
@@ -73,7 +73,7 @@ Type_Info_Rune :: struct {}
|
||||
Type_Info_Float :: struct {endianness: Platform_Endianness}
|
||||
Type_Info_Complex :: struct {}
|
||||
Type_Info_Quaternion :: struct {}
|
||||
Type_Info_String :: struct {is_cstring: bool}
|
||||
Type_Info_String :: struct {is_cstring: bool, is_utf16: bool}
|
||||
Type_Info_Boolean :: struct {}
|
||||
Type_Info_Any :: struct {}
|
||||
Type_Info_Type_Id :: struct {}
|
||||
@@ -397,6 +397,11 @@ Raw_String :: struct {
|
||||
len: int,
|
||||
}
|
||||
|
||||
Raw_String16 :: struct {
|
||||
data: [^]u16,
|
||||
len: int,
|
||||
}
|
||||
|
||||
Raw_Slice :: struct {
|
||||
data: rawptr,
|
||||
len: int,
|
||||
@@ -450,6 +455,12 @@ Raw_Cstring :: struct {
|
||||
}
|
||||
#assert(size_of(Raw_Cstring) == size_of(cstring))
|
||||
|
||||
Raw_Cstring16 :: struct {
|
||||
data: [^]u16,
|
||||
}
|
||||
#assert(size_of(Raw_Cstring16) == size_of(cstring16))
|
||||
|
||||
|
||||
Raw_Soa_Pointer :: struct {
|
||||
data: rawptr,
|
||||
index: int,
|
||||
|
||||
@@ -86,11 +86,26 @@ copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// `copy_from_string16` is a built-in procedure that copies elements from a source string `src` to a destination slice `dst`.
|
||||
// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
|
||||
// of len(src) and len(dst).
|
||||
//
|
||||
// Prefer the procedure group `copy`.
|
||||
@builtin
|
||||
copy_from_string16 :: proc "contextless" (dst: $T/[]$E/u16, src: $S/string16) -> int {
|
||||
n := min(len(dst), len(src))
|
||||
if n > 0 {
|
||||
intrinsics.mem_copy(raw_data(dst), raw_data(src), n*size_of(u16))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// `copy` is a built-in procedure that copies elements from a source slice/string `src` to a destination slice `dst`.
|
||||
// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
|
||||
// of len(src) and len(dst).
|
||||
@builtin
|
||||
copy :: proc{copy_slice, copy_from_string}
|
||||
copy :: proc{copy_slice, copy_from_string, copy_from_string16}
|
||||
|
||||
|
||||
|
||||
@@ -285,6 +300,15 @@ delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error
|
||||
}
|
||||
|
||||
|
||||
@builtin
|
||||
delete_string16 :: proc(str: string16, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||
return mem_free_with_size(raw_data(str), len(str)*size_of(u16), allocator, loc)
|
||||
}
|
||||
@builtin
|
||||
delete_cstring16 :: proc(str: cstring16, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||
return mem_free((^u16)(str), allocator, loc)
|
||||
}
|
||||
|
||||
// `delete` will try to free the underlying data of the passed built-in data structure (string, cstring, dynamic array, slice, or map), with the given `allocator` if the allocator supports this operation.
|
||||
//
|
||||
// Note: Prefer `delete` over the specific `delete_*` procedures where possible.
|
||||
@@ -297,6 +321,8 @@ delete :: proc{
|
||||
delete_map,
|
||||
delete_soa_slice,
|
||||
delete_soa_dynamic_array,
|
||||
delete_string16,
|
||||
delete_cstring16,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -493,12 +493,40 @@ string_cmp :: proc "contextless" (a, b: string) -> int {
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
string16_eq :: proc "contextless" (lhs, rhs: string16) -> bool {
|
||||
x := transmute(Raw_String16)lhs
|
||||
y := transmute(Raw_String16)rhs
|
||||
if x.len != y.len {
|
||||
return false
|
||||
}
|
||||
return #force_inline memory_equal(x.data, y.data, x.len*size_of(u16))
|
||||
}
|
||||
|
||||
string16_cmp :: proc "contextless" (a, b: string16) -> int {
|
||||
x := transmute(Raw_String16)a
|
||||
y := transmute(Raw_String16)b
|
||||
|
||||
ret := memory_compare(x.data, y.data, min(x.len, y.len)*size_of(u16))
|
||||
if ret == 0 && x.len != y.len {
|
||||
return -1 if x.len < y.len else +1
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
string_ne :: #force_inline proc "contextless" (a, b: string) -> bool { return !string_eq(a, b) }
|
||||
string_lt :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) < 0 }
|
||||
string_gt :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) > 0 }
|
||||
string_le :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) <= 0 }
|
||||
string_ge :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) >= 0 }
|
||||
|
||||
string16_ne :: #force_inline proc "contextless" (a, b: string16) -> bool { return !string16_eq(a, b) }
|
||||
string16_lt :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) < 0 }
|
||||
string16_gt :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) > 0 }
|
||||
string16_le :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) <= 0 }
|
||||
string16_ge :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) >= 0 }
|
||||
|
||||
|
||||
cstring_len :: proc "contextless" (s: cstring) -> int {
|
||||
p0 := uintptr((^byte)(s))
|
||||
p := p0
|
||||
@@ -508,6 +536,16 @@ cstring_len :: proc "contextless" (s: cstring) -> int {
|
||||
return int(p - p0)
|
||||
}
|
||||
|
||||
cstring16_len :: proc "contextless" (s: cstring16) -> int {
|
||||
p := ([^]u16)(s)
|
||||
n := 0
|
||||
for p != nil && p[0] != 0 {
|
||||
p = p[1:]
|
||||
n += 1
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
cstring_to_string :: proc "contextless" (s: cstring) -> string {
|
||||
if s == nil {
|
||||
return ""
|
||||
@@ -517,6 +555,15 @@ cstring_to_string :: proc "contextless" (s: cstring) -> string {
|
||||
return transmute(string)Raw_String{ptr, n}
|
||||
}
|
||||
|
||||
cstring16_to_string16 :: proc "contextless" (s: cstring16) -> string16 {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
ptr := (^u16)(s)
|
||||
n := cstring16_len(s)
|
||||
return transmute(string16)Raw_String16{ptr, n}
|
||||
}
|
||||
|
||||
|
||||
cstring_eq :: proc "contextless" (lhs, rhs: cstring) -> bool {
|
||||
x := ([^]byte)(lhs)
|
||||
@@ -559,6 +606,46 @@ cstring_gt :: #force_inline proc "contextless" (a, b: cstring) -> bool { return
|
||||
cstring_le :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_cmp(a, b) <= 0 }
|
||||
cstring_ge :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_cmp(a, b) >= 0 }
|
||||
|
||||
cstring16_eq :: proc "contextless" (lhs, rhs: cstring16) -> bool {
|
||||
x := ([^]u16)(lhs)
|
||||
y := ([^]u16)(rhs)
|
||||
if x == y {
|
||||
return true
|
||||
}
|
||||
if (x == nil) ~ (y == nil) {
|
||||
return false
|
||||
}
|
||||
xn := cstring16_len(lhs)
|
||||
yn := cstring16_len(rhs)
|
||||
if xn != yn {
|
||||
return false
|
||||
}
|
||||
return #force_inline memory_equal(x, y, xn*size_of(u16))
|
||||
}
|
||||
|
||||
cstring16_cmp :: proc "contextless" (lhs, rhs: cstring16) -> int {
|
||||
x := ([^]u16)(lhs)
|
||||
y := ([^]u16)(rhs)
|
||||
if x == y {
|
||||
return 0
|
||||
}
|
||||
if (x == nil) ~ (y == nil) {
|
||||
return -1 if x == nil else +1
|
||||
}
|
||||
xn := cstring16_len(lhs)
|
||||
yn := cstring16_len(rhs)
|
||||
ret := memory_compare(x, y, min(xn, yn)*size_of(u16))
|
||||
if ret == 0 && xn != yn {
|
||||
return -1 if xn < yn else +1
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
cstring16_ne :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return !cstring16_eq(a, b) }
|
||||
cstring16_lt :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) < 0 }
|
||||
cstring16_gt :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) > 0 }
|
||||
cstring16_le :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) <= 0 }
|
||||
cstring16_ge :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) >= 0 }
|
||||
|
||||
complex32_eq :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) == real(b) && imag(a) == imag(b) }
|
||||
complex32_ne :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) != real(b) || imag(a) != imag(b) }
|
||||
|
||||
Reference in New Issue
Block a user