mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
for in string16; Support string16 across core
This commit is contained in:
@@ -781,6 +781,68 @@ string_decode_last_rune :: proc "contextless" (s: string) -> (rune, int) {
|
|||||||
return r, size
|
return r, size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string16_decode_rune :: #force_inline proc "contextless" (s: string16) -> (rune, int) {
|
||||||
|
REPLACEMENT_CHAR :: '\ufffd'
|
||||||
|
_surr1 :: 0xd800
|
||||||
|
_surr2 :: 0xdc00
|
||||||
|
_surr3 :: 0xe000
|
||||||
|
_surr_self :: 0x10000
|
||||||
|
|
||||||
|
r := rune(REPLACEMENT_CHAR)
|
||||||
|
|
||||||
|
if len(s) < 1 {
|
||||||
|
return r, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
w := 1
|
||||||
|
switch c := s[0]; {
|
||||||
|
case c < _surr1, _surr3 <= c:
|
||||||
|
r = rune(c)
|
||||||
|
case _surr1 <= c && c < _surr2 && 1 < len(s) &&
|
||||||
|
_surr2 <= s[1] && s[1] < _surr3:
|
||||||
|
r1, r2 := rune(c), rune(s[1])
|
||||||
|
if _surr1 <= r1 && r1 < _surr2 && _surr2 <= r2 && r2 < _surr3 {
|
||||||
|
r = (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self
|
||||||
|
}
|
||||||
|
w += 1
|
||||||
|
}
|
||||||
|
return r, w
|
||||||
|
}
|
||||||
|
|
||||||
|
string16_decode_last_rune :: proc "contextless" (s: string16) -> (rune, int) {
|
||||||
|
REPLACEMENT_CHAR :: '\ufffd'
|
||||||
|
_surr1 :: 0xd800
|
||||||
|
_surr2 :: 0xdc00
|
||||||
|
_surr3 :: 0xe000
|
||||||
|
_surr_self :: 0x10000
|
||||||
|
|
||||||
|
r := rune(REPLACEMENT_CHAR)
|
||||||
|
|
||||||
|
if len(s) < 1 {
|
||||||
|
return r, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
n := len(s)-1
|
||||||
|
c := s[n]
|
||||||
|
w := 1
|
||||||
|
if _surr2 <= c && c < _surr3 {
|
||||||
|
if n >= 1 {
|
||||||
|
r1 := rune(s[n-1])
|
||||||
|
r2 := rune(c)
|
||||||
|
if _surr1 <= r1 && r1 < _surr2 {
|
||||||
|
r = (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self
|
||||||
|
}
|
||||||
|
w = 2
|
||||||
|
}
|
||||||
|
} else if c < _surr1 || _surr3 <= c {
|
||||||
|
r = rune(c)
|
||||||
|
}
|
||||||
|
return r, w
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 {
|
abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 {
|
||||||
p, q := abs(real(x)), abs(imag(x))
|
p, q := abs(real(x)), abs(imag(x))
|
||||||
if p < q {
|
if p < q {
|
||||||
|
|||||||
@@ -72,14 +72,14 @@ when ODIN_OS == .Windows {
|
|||||||
n_sep_by_space: c.char,
|
n_sep_by_space: c.char,
|
||||||
p_sign_posn: c.char,
|
p_sign_posn: c.char,
|
||||||
n_sign_posn: c.char,
|
n_sign_posn: c.char,
|
||||||
_W_decimal_point: [^]u16 `fmt:"s,0"`,
|
_W_decimal_point: cstring16,
|
||||||
_W_thousands_sep: [^]u16 `fmt:"s,0"`,
|
_W_thousands_sep: cstring16,
|
||||||
_W_int_curr_symbol: [^]u16 `fmt:"s,0"`,
|
_W_int_curr_symbol: cstring16,
|
||||||
_W_currency_symbol: [^]u16 `fmt:"s,0"`,
|
_W_currency_symbol: cstring16,
|
||||||
_W_mon_decimal_point: [^]u16 `fmt:"s,0"`,
|
_W_mon_decimal_point: cstring16,
|
||||||
_W_mon_thousands_sep: [^]u16 `fmt:"s,0"`,
|
_W_mon_thousands_sep: cstring16,
|
||||||
_W_positive_sign: [^]u16 `fmt:"s,0"`,
|
_W_positive_sign: cstring16,
|
||||||
_W_negative_sign: [^]u16 `fmt:"s,0"`,
|
_W_negative_sign: cstring16,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lconv :: struct {
|
lconv :: struct {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ _resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> (
|
|||||||
symbol.SizeOfStruct = size_of(symbol^)
|
symbol.SizeOfStruct = size_of(symbol^)
|
||||||
symbol.MaxNameLen = 255
|
symbol.MaxNameLen = 255
|
||||||
if win32.SymFromAddrW(ctx.impl.hProcess, win32.DWORD64(frame), &{}, symbol) {
|
if win32.SymFromAddrW(ctx.impl.hProcess, win32.DWORD64(frame), &{}, symbol) {
|
||||||
fl.procedure, _ = win32.wstring_to_utf8(&symbol.Name[0], -1, allocator)
|
fl.procedure, _ = win32.wstring_to_utf8(cstring16(&symbol.Name[0]), -1, allocator)
|
||||||
} else {
|
} else {
|
||||||
fl.procedure = fmt.aprintf("(procedure: 0x%x)", frame, allocator=allocator)
|
fl.procedure = fmt.aprintf("(procedure: 0x%x)", frame, allocator=allocator)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ _LIBRARY_FILE_EXTENSION :: "dll"
|
|||||||
_load_library :: proc(path: string, global_symbols: bool, allocator: runtime.Allocator) -> (Library, bool) {
|
_load_library :: proc(path: string, global_symbols: bool, allocator: runtime.Allocator) -> (Library, bool) {
|
||||||
// NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL
|
// NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL
|
||||||
wide_path := win32.utf8_to_wstring(path, allocator)
|
wide_path := win32.utf8_to_wstring(path, allocator)
|
||||||
defer free(wide_path, allocator)
|
defer free(rawptr(wide_path), allocator)
|
||||||
handle := cast(Library)win32.LoadLibraryW(wide_path)
|
handle := cast(Library)win32.LoadLibraryW(wide_path)
|
||||||
return handle, handle != nil
|
return handle, handle != nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ foreign Kernel32 {
|
|||||||
flProtect: u32,
|
flProtect: u32,
|
||||||
dwMaximumSizeHigh: u32,
|
dwMaximumSizeHigh: u32,
|
||||||
dwMaximumSizeLow: u32,
|
dwMaximumSizeLow: u32,
|
||||||
lpName: [^]u16,
|
lpName: cstring16,
|
||||||
) -> rawptr ---
|
) -> rawptr ---
|
||||||
|
|
||||||
MapViewOfFile :: proc(
|
MapViewOfFile :: proc(
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
|
|||||||
defer delete(path)
|
defer delete(path)
|
||||||
|
|
||||||
find_data := &win32.WIN32_FIND_DATAW{}
|
find_data := &win32.WIN32_FIND_DATAW{}
|
||||||
find_handle := win32.FindFirstFileW(raw_data(wpath_search), find_data)
|
find_handle := win32.FindFirstFileW(cstring16(raw_data(wpath_search)), find_data)
|
||||||
if find_handle == win32.INVALID_HANDLE_VALUE {
|
if find_handle == win32.INVALID_HANDLE_VALUE {
|
||||||
err = get_last_error()
|
err = get_last_error()
|
||||||
return dfi[:], err
|
return dfi[:], err
|
||||||
|
|||||||
@@ -619,7 +619,7 @@ _symlink :: proc(old_name, new_name: string) -> Error {
|
|||||||
return .Unsupported
|
return .Unsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
_open_sym_link :: proc(p: [^]u16) -> (handle: win32.HANDLE, err: Error) {
|
_open_sym_link :: proc(p: cstring16) -> (handle: win32.HANDLE, err: Error) {
|
||||||
attrs := u32(win32.FILE_FLAG_BACKUP_SEMANTICS)
|
attrs := u32(win32.FILE_FLAG_BACKUP_SEMANTICS)
|
||||||
attrs |= win32.FILE_FLAG_OPEN_REPARSE_POINT
|
attrs |= win32.FILE_FLAG_OPEN_REPARSE_POINT
|
||||||
handle = win32.CreateFileW(p, 0, 0, nil, win32.OPEN_EXISTING, attrs, nil)
|
handle = win32.CreateFileW(p, 0, 0, nil, win32.OPEN_EXISTING, attrs, nil)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ full_path_from_name :: proc(name: string, allocator := context.allocator) -> (pa
|
|||||||
buf := make([dynamic]u16, 100)
|
buf := make([dynamic]u16, 100)
|
||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
for {
|
for {
|
||||||
n := win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil)
|
n := win32.GetFullPathNameW(cstring16(raw_data(p)), u32(len(buf)), cstring16(raw_data(buf)), nil)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return "", get_last_error()
|
return "", get_last_error()
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ cleanpath_from_handle_u16 :: proc(fd: Handle, allocator: runtime.Allocator) -> (
|
|||||||
return nil, get_last_error()
|
return nil, get_last_error()
|
||||||
}
|
}
|
||||||
buf := make([]u16, max(n, win32.DWORD(260))+1, allocator)
|
buf := make([]u16, max(n, win32.DWORD(260))+1, allocator)
|
||||||
buf_len := win32.GetFinalPathNameByHandleW(h, raw_data(buf), n, 0)
|
buf_len := win32.GetFinalPathNameByHandleW(h, cstring16(raw_data(buf)), n, 0)
|
||||||
return buf[:buf_len], nil
|
return buf[:buf_len], nil
|
||||||
}
|
}
|
||||||
@(private, require_results)
|
@(private, require_results)
|
||||||
|
|||||||
@@ -61,13 +61,13 @@ temp_full_path :: proc(name: string) -> (path: string, err: os.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p := win32.utf8_to_utf16(name, ta)
|
p := win32.utf8_to_utf16(name, ta)
|
||||||
n := win32.GetFullPathNameW(raw_data(p), 0, nil, nil)
|
n := win32.GetFullPathNameW(cstring16(raw_data(p)), 0, nil, nil)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return "", os.get_last_error()
|
return "", os.get_last_error()
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]u16, n, ta)
|
buf := make([]u16, n, ta)
|
||||||
n = win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil)
|
n = win32.GetFullPathNameW(cstring16(raw_data(p)), u32(len(buf)), cstring16(raw_data(buf)), nil)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
delete(buf)
|
delete(buf)
|
||||||
return "", os.get_last_error()
|
return "", os.get_last_error()
|
||||||
|
|||||||
@@ -324,8 +324,8 @@ read_reg_string :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: string, ok
|
|||||||
|
|
||||||
status := sys.RegGetValueW(
|
status := sys.RegGetValueW(
|
||||||
hkey,
|
hkey,
|
||||||
&key_name_wide[0],
|
cstring16(&key_name_wide[0]),
|
||||||
&val_name_wide[0],
|
cstring16(&val_name_wide[0]),
|
||||||
sys.RRF_RT_REG_SZ,
|
sys.RRF_RT_REG_SZ,
|
||||||
nil,
|
nil,
|
||||||
raw_data(result_wide[:]),
|
raw_data(result_wide[:]),
|
||||||
@@ -359,8 +359,8 @@ read_reg_i32 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i32, ok: bool
|
|||||||
result_size := sys.DWORD(size_of(i32))
|
result_size := sys.DWORD(size_of(i32))
|
||||||
status := sys.RegGetValueW(
|
status := sys.RegGetValueW(
|
||||||
hkey,
|
hkey,
|
||||||
&key_name_wide[0],
|
cstring16(&key_name_wide[0]),
|
||||||
&val_name_wide[0],
|
cstring16(&val_name_wide[0]),
|
||||||
sys.RRF_RT_REG_DWORD,
|
sys.RRF_RT_REG_DWORD,
|
||||||
nil,
|
nil,
|
||||||
&res,
|
&res,
|
||||||
@@ -386,8 +386,8 @@ read_reg_i64 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i64, ok: bool
|
|||||||
result_size := sys.DWORD(size_of(i64))
|
result_size := sys.DWORD(size_of(i64))
|
||||||
status := sys.RegGetValueW(
|
status := sys.RegGetValueW(
|
||||||
hkey,
|
hkey,
|
||||||
&key_name_wide[0],
|
cstring16(&key_name_wide[0]),
|
||||||
&val_name_wide[0],
|
cstring16(&val_name_wide[0]),
|
||||||
sys.RRF_RT_REG_QWORD,
|
sys.RRF_RT_REG_QWORD,
|
||||||
nil,
|
nil,
|
||||||
&res,
|
&res,
|
||||||
|
|||||||
@@ -573,10 +573,10 @@ Button_GetTextMargin :: #force_inline proc "system" (hwnd: HWND, pmargin: ^RECT)
|
|||||||
return cast(BOOL)SendMessageW(hwnd, BCM_GETTEXTMARGIN, 0, cast(LPARAM)uintptr(pmargin))
|
return cast(BOOL)SendMessageW(hwnd, BCM_GETTEXTMARGIN, 0, cast(LPARAM)uintptr(pmargin))
|
||||||
}
|
}
|
||||||
Button_SetNote :: #force_inline proc "system" (hwnd: HWND, psz: LPCWSTR) -> BOOL {
|
Button_SetNote :: #force_inline proc "system" (hwnd: HWND, psz: LPCWSTR) -> BOOL {
|
||||||
return cast(BOOL)SendMessageW(hwnd, BCM_SETNOTE, 0, cast(LPARAM)uintptr(psz))
|
return cast(BOOL)SendMessageW(hwnd, BCM_SETNOTE, 0, cast(LPARAM)uintptr(rawptr(psz)))
|
||||||
}
|
}
|
||||||
Button_GetNote :: #force_inline proc "system" (hwnd: HWND, psz: LPCWSTR, pcc: ^c_int) -> BOOL {
|
Button_GetNote :: #force_inline proc "system" (hwnd: HWND, psz: LPCWSTR, pcc: ^c_int) -> BOOL {
|
||||||
return cast(BOOL)SendMessageW(hwnd, BCM_GETNOTE, uintptr(pcc), cast(LPARAM)uintptr(psz))
|
return cast(BOOL)SendMessageW(hwnd, BCM_GETNOTE, uintptr(pcc), cast(LPARAM)uintptr(rawptr(psz)))
|
||||||
}
|
}
|
||||||
Button_GetNoteLength :: #force_inline proc "system" (hwnd: HWND) -> LRESULT {
|
Button_GetNoteLength :: #force_inline proc "system" (hwnd: HWND) -> LRESULT {
|
||||||
return SendMessageW(hwnd, BCM_GETNOTELENGTH, 0, 0)
|
return SendMessageW(hwnd, BCM_GETNOTELENGTH, 0, 0)
|
||||||
@@ -604,10 +604,10 @@ EDITBALLOONTIP :: struct {
|
|||||||
PEDITBALLOONTIP :: ^EDITBALLOONTIP
|
PEDITBALLOONTIP :: ^EDITBALLOONTIP
|
||||||
|
|
||||||
Edit_SetCueBannerText :: #force_inline proc "system" (hwnd: HWND, lpcwText: LPCWSTR) -> BOOL {
|
Edit_SetCueBannerText :: #force_inline proc "system" (hwnd: HWND, lpcwText: LPCWSTR) -> BOOL {
|
||||||
return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, 0, cast(LPARAM)uintptr(lpcwText))
|
return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, 0, cast(LPARAM)uintptr(rawptr(lpcwText)))
|
||||||
}
|
}
|
||||||
Edit_SetCueBannerTextFocused :: #force_inline proc "system" (hwnd: HWND, lpcwText: LPCWSTR, fDrawFocused: BOOL) -> BOOL {
|
Edit_SetCueBannerTextFocused :: #force_inline proc "system" (hwnd: HWND, lpcwText: LPCWSTR, fDrawFocused: BOOL) -> BOOL {
|
||||||
return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, cast(WPARAM)fDrawFocused, cast(LPARAM)uintptr(lpcwText))
|
return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, cast(WPARAM)fDrawFocused, cast(LPARAM)uintptr(rawptr(lpcwText)))
|
||||||
}
|
}
|
||||||
Edit_GetCueBannerText :: #force_inline proc "system" (hwnd: HWND, lpwText: LPWSTR, cchText: LONG) -> BOOL {
|
Edit_GetCueBannerText :: #force_inline proc "system" (hwnd: HWND, lpwText: LPWSTR, cchText: LONG) -> BOOL {
|
||||||
return cast(BOOL)SendMessageW(hwnd, EM_GETCUEBANNER, uintptr(lpwText), cast(LPARAM)cchText)
|
return cast(BOOL)SendMessageW(hwnd, EM_GETCUEBANNER, uintptr(lpwText), cast(LPARAM)cchText)
|
||||||
@@ -1197,7 +1197,7 @@ ListView_GetItemPosition :: #force_inline proc "system" (hwnd: HWND, i: c_int, p
|
|||||||
return cast(BOOL)SendMessageW(hwnd, LVM_GETITEMPOSITION, cast(WPARAM)i, cast(LPARAM)uintptr(ppt))
|
return cast(BOOL)SendMessageW(hwnd, LVM_GETITEMPOSITION, cast(WPARAM)i, cast(LPARAM)uintptr(ppt))
|
||||||
}
|
}
|
||||||
ListView_GetStringWidth :: #force_inline proc "system" (hwndLV: HWND, psz: LPCWSTR) -> c_int {
|
ListView_GetStringWidth :: #force_inline proc "system" (hwndLV: HWND, psz: LPCWSTR) -> c_int {
|
||||||
return cast(c_int)SendMessageW(hwndLV, LVM_GETSTRINGWIDTHW, 0, cast(LPARAM)uintptr(psz))
|
return cast(c_int)SendMessageW(hwndLV, LVM_GETSTRINGWIDTHW, 0, cast(LPARAM)uintptr(rawptr(psz)))
|
||||||
}
|
}
|
||||||
ListView_HitTest :: #force_inline proc "system" (hwndLV: HWND, pinfo: ^LV_HITTESTINFO) -> c_int {
|
ListView_HitTest :: #force_inline proc "system" (hwndLV: HWND, pinfo: ^LV_HITTESTINFO) -> c_int {
|
||||||
return cast(c_int)SendMessageW(hwndLV, LVM_HITTEST, 0, cast(LPARAM)uintptr(pinfo))
|
return cast(c_int)SendMessageW(hwndLV, LVM_HITTEST, 0, cast(LPARAM)uintptr(pinfo))
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ IP_Adapter_Addresses :: struct {
|
|||||||
FirstAnycastAddress: ^IP_ADAPTER_ANYCAST_ADDRESS_XP,
|
FirstAnycastAddress: ^IP_ADAPTER_ANYCAST_ADDRESS_XP,
|
||||||
FirstMulticastAddress: ^IP_ADAPTER_MULTICAST_ADDRESS_XP,
|
FirstMulticastAddress: ^IP_ADAPTER_MULTICAST_ADDRESS_XP,
|
||||||
FirstDnsServerAddress: ^IP_ADAPTER_DNS_SERVER_ADDRESS_XP,
|
FirstDnsServerAddress: ^IP_ADAPTER_DNS_SERVER_ADDRESS_XP,
|
||||||
DnsSuffix: ^u16,
|
DnsSuffix: cstring16,
|
||||||
Description: ^u16,
|
Description: cstring16,
|
||||||
FriendlyName: ^u16,
|
FriendlyName: cstring16,
|
||||||
PhysicalAddress: [8]u8,
|
PhysicalAddress: [8]u8,
|
||||||
PhysicalAddressLength: u32,
|
PhysicalAddressLength: u32,
|
||||||
Anonymous2: struct #raw_union {
|
Anonymous2: struct #raw_union {
|
||||||
|
|||||||
@@ -107,8 +107,8 @@ PDWORD64 :: ^DWORD64
|
|||||||
PDWORD_PTR :: ^DWORD_PTR
|
PDWORD_PTR :: ^DWORD_PTR
|
||||||
ATOM :: distinct WORD
|
ATOM :: distinct WORD
|
||||||
|
|
||||||
wstring :: [^]WCHAR
|
wstring :: cstring16
|
||||||
PWSTR :: [^]WCHAR
|
PWSTR :: cstring16
|
||||||
|
|
||||||
PBYTE :: ^BYTE
|
PBYTE :: ^BYTE
|
||||||
LPBYTE :: ^BYTE
|
LPBYTE :: ^BYTE
|
||||||
|
|||||||
+25
-25
@@ -122,14 +122,14 @@ utf8_to_utf16 :: proc{utf8_to_utf16_alloc, utf8_to_utf16_buf}
|
|||||||
|
|
||||||
utf8_to_wstring_alloc :: proc(s: string, allocator := context.temp_allocator) -> wstring {
|
utf8_to_wstring_alloc :: proc(s: string, allocator := context.temp_allocator) -> wstring {
|
||||||
if res := utf8_to_utf16(s, allocator); len(res) > 0 {
|
if res := utf8_to_utf16(s, allocator); len(res) > 0 {
|
||||||
return raw_data(res)
|
return wstring(raw_data(res))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8_to_wstring_buf :: proc(buf: []u16, s: string) -> wstring {
|
utf8_to_wstring_buf :: proc(buf: []u16, s: string) -> wstring {
|
||||||
if res := utf8_to_utf16(buf, s); len(res) > 0 {
|
if res := utf8_to_utf16(buf, s); len(res) > 0 {
|
||||||
return raw_data(res)
|
return wstring(raw_data(res))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -215,7 +215,7 @@ utf16_to_utf8_alloc :: proc(s: []u16, allocator := context.temp_allocator) -> (r
|
|||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return wstring_to_utf8(raw_data(s), len(s), allocator)
|
return wstring_to_utf8(wstring(raw_data(s)), len(s), allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -236,7 +236,7 @@ utf16_to_utf8_buf :: proc(buf: []u8, s: []u16) -> (res: string) {
|
|||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return wstring_to_utf8(buf, raw_data(s), len(s))
|
return wstring_to_utf8(buf, wstring(raw_data(s)), len(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
utf16_to_utf8 :: proc{utf16_to_utf8_alloc, utf16_to_utf8_buf}
|
utf16_to_utf8 :: proc{utf16_to_utf8_alloc, utf16_to_utf8_buf}
|
||||||
@@ -298,7 +298,7 @@ _add_user :: proc(servername: string, username: string, password: string) -> (ok
|
|||||||
servername_w = nil
|
servername_w = nil
|
||||||
} else {
|
} else {
|
||||||
server := utf8_to_utf16(servername, context.temp_allocator)
|
server := utf8_to_utf16(servername, context.temp_allocator)
|
||||||
servername_w = &server[0]
|
servername_w = wstring(&server[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(username) == 0 || len(username) > LM20_UNLEN {
|
if len(username) == 0 || len(username) > LM20_UNLEN {
|
||||||
@@ -348,7 +348,7 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s
|
|||||||
|
|
||||||
res := LookupAccountNameW(
|
res := LookupAccountNameW(
|
||||||
nil, // Look on this computer first
|
nil, // Look on this computer first
|
||||||
&username_w[0],
|
wstring(&username_w[0]),
|
||||||
&sid,
|
&sid,
|
||||||
&cbsid,
|
&cbsid,
|
||||||
nil,
|
nil,
|
||||||
@@ -364,10 +364,10 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s
|
|||||||
|
|
||||||
res = LookupAccountNameW(
|
res = LookupAccountNameW(
|
||||||
nil,
|
nil,
|
||||||
&username_w[0],
|
wstring(&username_w[0]),
|
||||||
&sid,
|
&sid,
|
||||||
&cbsid,
|
&cbsid,
|
||||||
&cname_w[0],
|
wstring(&cname_w[0]),
|
||||||
&computer_name_size,
|
&computer_name_size,
|
||||||
&pe_use,
|
&pe_use,
|
||||||
)
|
)
|
||||||
@@ -390,7 +390,7 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) {
|
|||||||
|
|
||||||
res := LookupAccountNameW(
|
res := LookupAccountNameW(
|
||||||
nil, // Look on this computer first
|
nil, // Look on this computer first
|
||||||
&username_w[0],
|
wstring(&username_w[0]),
|
||||||
sid,
|
sid,
|
||||||
&cbsid,
|
&cbsid,
|
||||||
nil,
|
nil,
|
||||||
@@ -406,10 +406,10 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) {
|
|||||||
|
|
||||||
res = LookupAccountNameW(
|
res = LookupAccountNameW(
|
||||||
nil,
|
nil,
|
||||||
&username_w[0],
|
wstring(&username_w[0]),
|
||||||
sid,
|
sid,
|
||||||
&cbsid,
|
&cbsid,
|
||||||
&cname_w[0],
|
wstring(&cname_w[0]),
|
||||||
&computer_name_size,
|
&computer_name_size,
|
||||||
&pe_use,
|
&pe_use,
|
||||||
)
|
)
|
||||||
@@ -428,7 +428,7 @@ add_user_to_group :: proc(sid: ^SID, group: string) -> (ok: NET_API_STATUS) {
|
|||||||
group_name := utf8_to_utf16(group, context.temp_allocator)
|
group_name := utf8_to_utf16(group, context.temp_allocator)
|
||||||
ok = NetLocalGroupAddMembers(
|
ok = NetLocalGroupAddMembers(
|
||||||
nil,
|
nil,
|
||||||
&group_name[0],
|
wstring(&group_name[0]),
|
||||||
0,
|
0,
|
||||||
&group_member,
|
&group_member,
|
||||||
1,
|
1,
|
||||||
@@ -443,7 +443,7 @@ add_del_from_group :: proc(sid: ^SID, group: string) -> (ok: NET_API_STATUS) {
|
|||||||
group_name := utf8_to_utf16(group, context.temp_allocator)
|
group_name := utf8_to_utf16(group, context.temp_allocator)
|
||||||
ok = NetLocalGroupDelMembers(
|
ok = NetLocalGroupDelMembers(
|
||||||
nil,
|
nil,
|
||||||
&group_name[0],
|
cstring16(&group_name[0]),
|
||||||
0,
|
0,
|
||||||
&group_member,
|
&group_member,
|
||||||
1,
|
1,
|
||||||
@@ -465,19 +465,19 @@ add_user_profile :: proc(username: string) -> (ok: bool, profile_path: string) {
|
|||||||
if res == false {
|
if res == false {
|
||||||
return false, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
defer LocalFree(sb)
|
defer LocalFree(rawptr(sb))
|
||||||
|
|
||||||
pszProfilePath := make([]u16, 257, context.temp_allocator)
|
pszProfilePath := make([]u16, 257, context.temp_allocator)
|
||||||
res2 := CreateProfile(
|
res2 := CreateProfile(
|
||||||
sb,
|
sb,
|
||||||
&username_w[0],
|
cstring16(&username_w[0]),
|
||||||
&pszProfilePath[0],
|
cstring16(&pszProfilePath[0]),
|
||||||
257,
|
257,
|
||||||
)
|
)
|
||||||
if res2 != 0 {
|
if res2 != 0 {
|
||||||
return false, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
profile_path = wstring_to_utf8(&pszProfilePath[0], 257) or_else ""
|
profile_path = wstring_to_utf8(wstring(&pszProfilePath[0]), 257) or_else ""
|
||||||
|
|
||||||
return true, profile_path
|
return true, profile_path
|
||||||
}
|
}
|
||||||
@@ -495,7 +495,7 @@ delete_user_profile :: proc(username: string) -> (ok: bool) {
|
|||||||
if res == false {
|
if res == false {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
defer LocalFree(sb)
|
defer LocalFree(rawptr(sb))
|
||||||
|
|
||||||
res2 := DeleteProfileW(
|
res2 := DeleteProfileW(
|
||||||
sb,
|
sb,
|
||||||
@@ -548,13 +548,13 @@ delete_user :: proc(servername: string, username: string) -> (ok: bool) {
|
|||||||
servername_w = nil
|
servername_w = nil
|
||||||
} else {
|
} else {
|
||||||
server := utf8_to_utf16(servername, context.temp_allocator)
|
server := utf8_to_utf16(servername, context.temp_allocator)
|
||||||
servername_w = &server[0]
|
servername_w = wstring(&server[0])
|
||||||
}
|
}
|
||||||
username_w := utf8_to_utf16(username)
|
username_w := utf8_to_utf16(username)
|
||||||
|
|
||||||
res := NetUserDel(
|
res := NetUserDel(
|
||||||
servername_w,
|
servername_w,
|
||||||
&username_w[0],
|
wstring(&username_w[0]),
|
||||||
)
|
)
|
||||||
if res != .Success {
|
if res != .Success {
|
||||||
return false
|
return false
|
||||||
@@ -586,9 +586,9 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P
|
|||||||
user_token: HANDLE
|
user_token: HANDLE
|
||||||
|
|
||||||
ok = bool(LogonUserW(
|
ok = bool(LogonUserW(
|
||||||
lpszUsername = &username_w[0],
|
lpszUsername = wstring(&username_w[0]),
|
||||||
lpszDomain = &domain_w[0],
|
lpszDomain = wstring(&domain_w[0]),
|
||||||
lpszPassword = &password_w[0],
|
lpszPassword = wstring(&password_w[0]),
|
||||||
dwLogonType = .NEW_CREDENTIALS,
|
dwLogonType = .NEW_CREDENTIALS,
|
||||||
dwLogonProvider = .WINNT50,
|
dwLogonProvider = .WINNT50,
|
||||||
phToken = &user_token,
|
phToken = &user_token,
|
||||||
@@ -605,8 +605,8 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P
|
|||||||
|
|
||||||
ok = bool(CreateProcessAsUserW(
|
ok = bool(CreateProcessAsUserW(
|
||||||
user_token,
|
user_token,
|
||||||
&app_w[0],
|
wstring(&app_w[0]),
|
||||||
&commandline_w[0],
|
wstring(&commandline_w[0]),
|
||||||
nil, // lpProcessAttributes,
|
nil, // lpProcessAttributes,
|
||||||
nil, // lpThreadAttributes,
|
nil, // lpThreadAttributes,
|
||||||
false, // bInheritHandles,
|
false, // bInheritHandles,
|
||||||
|
|||||||
@@ -159,9 +159,9 @@ iana_to_windows_tz :: proc(iana_name: string, allocator := context.allocator) ->
|
|||||||
status: windows.UError
|
status: windows.UError
|
||||||
|
|
||||||
iana_name_wstr := windows.utf8_to_wstring(iana_name, allocator)
|
iana_name_wstr := windows.utf8_to_wstring(iana_name, allocator)
|
||||||
defer free(iana_name_wstr, allocator)
|
defer free(rawptr(iana_name_wstr), allocator)
|
||||||
|
|
||||||
wintz_name_len := windows.ucal_getWindowsTimeZoneID(iana_name_wstr, -1, raw_data(wintz_name_buffer[:]), len(wintz_name_buffer), &status)
|
wintz_name_len := windows.ucal_getWindowsTimeZoneID(iana_name_wstr, -1, cstring16(raw_data(wintz_name_buffer[:])), len(wintz_name_buffer), &status)
|
||||||
if status != .U_ZERO_ERROR {
|
if status != .U_ZERO_ERROR {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ local_tz_name :: proc(allocator := context.allocator) -> (name: string, success:
|
|||||||
iana_name_buffer: [128]u16
|
iana_name_buffer: [128]u16
|
||||||
status: windows.UError
|
status: windows.UError
|
||||||
|
|
||||||
zone_str_len := windows.ucal_getDefaultTimeZone(raw_data(iana_name_buffer[:]), len(iana_name_buffer), &status)
|
zone_str_len := windows.ucal_getDefaultTimeZone(cstring16(raw_data(iana_name_buffer[:])), len(iana_name_buffer), &status)
|
||||||
if status != .U_ZERO_ERROR {
|
if status != .U_ZERO_ERROR {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -291,7 +291,7 @@ _region_load :: proc(reg_str: string, allocator := context.allocator) -> (out_re
|
|||||||
defer delete(tz_key, allocator)
|
defer delete(tz_key, allocator)
|
||||||
|
|
||||||
tz_key_wstr := windows.utf8_to_wstring(tz_key, allocator)
|
tz_key_wstr := windows.utf8_to_wstring(tz_key, allocator)
|
||||||
defer free(tz_key_wstr, allocator)
|
defer free(rawptr(tz_key_wstr), allocator)
|
||||||
|
|
||||||
key: windows.HKEY
|
key: windows.HKEY
|
||||||
res := windows.RegOpenKeyExW(windows.HKEY_LOCAL_MACHINE, tz_key_wstr, 0, windows.KEY_READ, &key)
|
res := windows.RegOpenKeyExW(windows.HKEY_LOCAL_MACHINE, tz_key_wstr, 0, windows.KEY_READ, &key)
|
||||||
|
|||||||
@@ -126,7 +126,37 @@ decode_rune_in_string :: proc(s: string16) -> (r: rune, width: int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rune_count :: proc(s: []u16) -> (n: int) {
|
string_to_runes :: proc "odin" (s: string16, allocator := context.allocator) -> (runes: []rune) {
|
||||||
|
n := rune_count(s)
|
||||||
|
|
||||||
|
runes = make([]rune, n, allocator)
|
||||||
|
i := 0
|
||||||
|
for r in s {
|
||||||
|
runes[i] = r
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rune_count :: proc{
|
||||||
|
rune_count_in_string,
|
||||||
|
rune_count_in_slice,
|
||||||
|
}
|
||||||
|
rune_count_in_string :: proc(s: string16) -> (n: int) {
|
||||||
|
for i := 0; i < len(s); i += 1 {
|
||||||
|
c := s[i]
|
||||||
|
if _surr1 <= c && c < _surr2 && i+1 < len(s) &&
|
||||||
|
_surr2 <= s[i+1] && s[i+1] < _surr3 {
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
n += 1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rune_count_in_slice :: proc(s: []u16) -> (n: int) {
|
||||||
for i := 0; i < len(s); i += 1 {
|
for i := 0; i < len(s); i += 1 {
|
||||||
c := s[i]
|
c := s[i]
|
||||||
if _surr1 <= c && c < _surr2 && i+1 < len(s) &&
|
if _surr1 <= c && c < _surr2 && i+1 < len(s) &&
|
||||||
|
|||||||
@@ -7179,7 +7179,11 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
operand->mode = Addressing_Value;
|
operand->mode = Addressing_Value;
|
||||||
operand->type = alloc_type_multi_pointer(t_u16);
|
if (type_hint != nullptr && is_type_cstring16(type_hint)) {
|
||||||
|
operand->type = type_hint;
|
||||||
|
} else {
|
||||||
|
operand->type = alloc_type_multi_pointer(t_u16);
|
||||||
|
}
|
||||||
operand->value = {};
|
operand->value = {};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -3426,7 +3426,7 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type
|
|||||||
if (are_types_identical(src, t_cstring16) && is_type_u16_multi_ptr(dst)) {
|
if (are_types_identical(src, t_cstring16) && is_type_u16_multi_ptr(dst)) {
|
||||||
return !is_constant;
|
return !is_constant;
|
||||||
}
|
}
|
||||||
// cstring -> rawptr
|
// cstring16 -> rawptr
|
||||||
if (are_types_identical(src, t_cstring16) && is_type_rawptr(dst)) {
|
if (are_types_identical(src, t_cstring16) && is_type_rawptr(dst)) {
|
||||||
return !is_constant;
|
return !is_constant;
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-3
@@ -974,7 +974,14 @@ gb_internal void check_unroll_range_stmt(CheckerContext *ctx, Ast *node, u32 mod
|
|||||||
Type *t = base_type(operand.type);
|
Type *t = base_type(operand.type);
|
||||||
switch (t->kind) {
|
switch (t->kind) {
|
||||||
case Type_Basic:
|
case Type_Basic:
|
||||||
if (is_type_string(t) && t->Basic.kind != Basic_cstring) {
|
if (is_type_string16(t) && t->Basic.kind != Basic_cstring) {
|
||||||
|
val0 = t_rune;
|
||||||
|
val1 = t_int;
|
||||||
|
inline_for_depth = exact_value_i64(operand.value.value_string.len);
|
||||||
|
if (unroll_count > 0) {
|
||||||
|
error(node, "#unroll(%lld) does not support strings", cast(long long)unroll_count);
|
||||||
|
}
|
||||||
|
} else if (is_type_string(t) && t->Basic.kind != Basic_cstring) {
|
||||||
val0 = t_rune;
|
val0 = t_rune;
|
||||||
val1 = t_int;
|
val1 = t_int;
|
||||||
inline_for_depth = exact_value_i64(operand.value.value_string.len);
|
inline_for_depth = exact_value_i64(operand.value.value_string.len);
|
||||||
@@ -1236,7 +1243,11 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags
|
|||||||
|
|
||||||
add_to_seen_map(ctx, &seen, upper_op, x, lhs, rhs);
|
add_to_seen_map(ctx, &seen, upper_op, x, lhs, rhs);
|
||||||
|
|
||||||
if (is_type_string(x.type)) {
|
if (is_type_string16(x.type)) {
|
||||||
|
// NOTE(bill): Force dependency for strings here
|
||||||
|
add_package_dependency(ctx, "runtime", "string16_le");
|
||||||
|
add_package_dependency(ctx, "runtime", "string16_lt");
|
||||||
|
} else if (is_type_string(x.type)) {
|
||||||
// NOTE(bill): Force dependency for strings here
|
// NOTE(bill): Force dependency for strings here
|
||||||
add_package_dependency(ctx, "runtime", "string_le");
|
add_package_dependency(ctx, "runtime", "string_le");
|
||||||
add_package_dependency(ctx, "runtime", "string_lt");
|
add_package_dependency(ctx, "runtime", "string_lt");
|
||||||
@@ -1770,7 +1781,16 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
|
|||||||
|
|
||||||
switch (t->kind) {
|
switch (t->kind) {
|
||||||
case Type_Basic:
|
case Type_Basic:
|
||||||
if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) {
|
if (t->Basic.kind == Basic_string16) {
|
||||||
|
is_possibly_addressable = false;
|
||||||
|
array_add(&vals, t_rune);
|
||||||
|
array_add(&vals, t_int);
|
||||||
|
if (is_reverse) {
|
||||||
|
add_package_dependency(ctx, "runtime", "string16_decode_last_rune");
|
||||||
|
} else {
|
||||||
|
add_package_dependency(ctx, "runtime", "string16_decode_rune");
|
||||||
|
}
|
||||||
|
} else if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) {
|
||||||
is_possibly_addressable = false;
|
is_possibly_addressable = false;
|
||||||
array_add(&vals, t_rune);
|
array_add(&vals, t_rune);
|
||||||
array_add(&vals, t_int);
|
array_add(&vals, t_int);
|
||||||
|
|||||||
+120
-1
@@ -622,6 +622,121 @@ gb_internal void lb_build_range_string(lbProcedure *p, lbValue expr, Type *val_t
|
|||||||
if (done_) *done_ = done;
|
if (done_) *done_ = done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gb_internal void lb_build_range_string16(lbProcedure *p, lbValue expr, Type *val_type,
|
||||||
|
lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_,
|
||||||
|
bool is_reverse) {
|
||||||
|
|
||||||
|
lbModule *m = p->module;
|
||||||
|
lbValue count = lb_const_int(m, t_int, 0);
|
||||||
|
Type *expr_type = base_type(expr.type);
|
||||||
|
switch (expr_type->kind) {
|
||||||
|
case Type_Basic:
|
||||||
|
count = lb_string_len(p, expr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GB_PANIC("Cannot do range_string of %s", type_to_string(expr_type));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbValue val = {};
|
||||||
|
lbValue idx = {};
|
||||||
|
lbBlock *loop = nullptr;
|
||||||
|
lbBlock *done = nullptr;
|
||||||
|
lbBlock *body = nullptr;
|
||||||
|
|
||||||
|
loop = lb_create_block(p, "for.string16.loop");
|
||||||
|
body = lb_create_block(p, "for.string16.body");
|
||||||
|
done = lb_create_block(p, "for.string16.done");
|
||||||
|
|
||||||
|
lbAddr offset_ = lb_add_local_generated(p, t_int, false);
|
||||||
|
lbValue offset = {};
|
||||||
|
lbValue cond = {};
|
||||||
|
|
||||||
|
if (!is_reverse) {
|
||||||
|
/*
|
||||||
|
for c, offset in str {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := 0
|
||||||
|
for offset < len(str) {
|
||||||
|
c, _w := string16_decode_rune(str[offset:])
|
||||||
|
...
|
||||||
|
offset += _w
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
lb_addr_store(p, offset_, lb_const_int(m, t_int, 0));
|
||||||
|
|
||||||
|
lb_emit_jump(p, loop);
|
||||||
|
lb_start_block(p, loop);
|
||||||
|
|
||||||
|
|
||||||
|
offset = lb_addr_load(p, offset_);
|
||||||
|
cond = lb_emit_comp(p, Token_Lt, offset, count);
|
||||||
|
} else {
|
||||||
|
// NOTE(bill): REVERSED LOGIC
|
||||||
|
/*
|
||||||
|
#reverse for c, offset in str {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := len(str)
|
||||||
|
for offset > 0 {
|
||||||
|
c, _w := string16_decode_last_rune(str[:offset])
|
||||||
|
offset -= _w
|
||||||
|
...
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
lb_addr_store(p, offset_, count);
|
||||||
|
|
||||||
|
lb_emit_jump(p, loop);
|
||||||
|
lb_start_block(p, loop);
|
||||||
|
|
||||||
|
offset = lb_addr_load(p, offset_);
|
||||||
|
cond = lb_emit_comp(p, Token_Gt, offset, lb_const_int(m, t_int, 0));
|
||||||
|
}
|
||||||
|
lb_emit_if(p, cond, body, done);
|
||||||
|
lb_start_block(p, body);
|
||||||
|
|
||||||
|
|
||||||
|
lbValue rune_and_len = {};
|
||||||
|
if (!is_reverse) {
|
||||||
|
lbValue str_elem = lb_emit_ptr_offset(p, lb_string_elem(p, expr), offset);
|
||||||
|
lbValue str_len = lb_emit_arith(p, Token_Sub, count, offset, t_int);
|
||||||
|
auto args = array_make<lbValue>(permanent_allocator(), 1);
|
||||||
|
args[0] = lb_emit_string16(p, str_elem, str_len);
|
||||||
|
|
||||||
|
rune_and_len = lb_emit_runtime_call(p, "string16_decode_rune", args);
|
||||||
|
lbValue len = lb_emit_struct_ev(p, rune_and_len, 1);
|
||||||
|
lb_addr_store(p, offset_, lb_emit_arith(p, Token_Add, offset, len, t_int));
|
||||||
|
|
||||||
|
idx = offset;
|
||||||
|
} else {
|
||||||
|
// NOTE(bill): REVERSED LOGIC
|
||||||
|
lbValue str_elem = lb_string_elem(p, expr);
|
||||||
|
lbValue str_len = offset;
|
||||||
|
auto args = array_make<lbValue>(permanent_allocator(), 1);
|
||||||
|
args[0] = lb_emit_string16(p, str_elem, str_len);
|
||||||
|
|
||||||
|
rune_and_len = lb_emit_runtime_call(p, "string16_decode_last_rune", args);
|
||||||
|
lbValue len = lb_emit_struct_ev(p, rune_and_len, 1);
|
||||||
|
lb_addr_store(p, offset_, lb_emit_arith(p, Token_Sub, offset, len, t_int));
|
||||||
|
|
||||||
|
idx = lb_addr_load(p, offset_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (val_type != nullptr) {
|
||||||
|
val = lb_emit_struct_ev(p, rune_and_len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val_) *val_ = val;
|
||||||
|
if (idx_) *idx_ = idx;
|
||||||
|
if (loop_) *loop_ = loop;
|
||||||
|
if (done_) *done_ = done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gb_internal Ast *lb_strip_and_prefix(Ast *ident) {
|
gb_internal Ast *lb_strip_and_prefix(Ast *ident) {
|
||||||
if (ident != nullptr) {
|
if (ident != nullptr) {
|
||||||
@@ -1138,7 +1253,11 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
|
|||||||
}
|
}
|
||||||
Type *t = base_type(string.type);
|
Type *t = base_type(string.type);
|
||||||
GB_ASSERT(!is_type_cstring(t));
|
GB_ASSERT(!is_type_cstring(t));
|
||||||
lb_build_range_string(p, string, val0_type, &val, &key, &loop, &done, rs->reverse);
|
if (is_type_string16(t)) {
|
||||||
|
lb_build_range_string16(p, string, val0_type, &val, &key, &loop, &done, rs->reverse);
|
||||||
|
} else {
|
||||||
|
lb_build_range_string(p, string, val0_type, &val, &key, &loop, &done, rs->reverse);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type_Tuple:
|
case Type_Tuple:
|
||||||
|
|||||||
@@ -191,6 +191,23 @@ gb_internal lbValue lb_emit_clamp(lbProcedure *p, Type *t, lbValue x, lbValue mi
|
|||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gb_internal lbValue lb_emit_string16(lbProcedure *p, lbValue str_elem, lbValue str_len) {
|
||||||
|
if (false && lb_is_const(str_elem) && lb_is_const(str_len)) {
|
||||||
|
LLVMValueRef values[2] = {
|
||||||
|
str_elem.value,
|
||||||
|
str_len.value,
|
||||||
|
};
|
||||||
|
lbValue res = {};
|
||||||
|
res.type = t_string16;
|
||||||
|
res.value = llvm_const_named_struct(p->module, t_string16, values, gb_count_of(values));
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
lbAddr res = lb_add_local_generated(p, t_string16, false);
|
||||||
|
lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 0), str_elem);
|
||||||
|
lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 1), str_len);
|
||||||
|
return lb_addr_load(p, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_internal lbValue lb_emit_string(lbProcedure *p, lbValue str_elem, lbValue str_len) {
|
gb_internal lbValue lb_emit_string(lbProcedure *p, lbValue str_elem, lbValue str_len) {
|
||||||
|
|||||||
Reference in New Issue
Block a user