Merge tag 'dev-2025-09'

This commit is contained in:
2025-09-14 10:09:53 -04:00
172 changed files with 5296 additions and 851 deletions
+8 -8
View File
@@ -72,14 +72,14 @@ when ODIN_OS == .Windows {
n_sep_by_space: c.char,
p_sign_posn: c.char,
n_sign_posn: c.char,
_W_decimal_point: [^]u16 `fmt:"s,0"`,
_W_thousands_sep: [^]u16 `fmt:"s,0"`,
_W_int_curr_symbol: [^]u16 `fmt:"s,0"`,
_W_currency_symbol: [^]u16 `fmt:"s,0"`,
_W_mon_decimal_point: [^]u16 `fmt:"s,0"`,
_W_mon_thousands_sep: [^]u16 `fmt:"s,0"`,
_W_positive_sign: [^]u16 `fmt:"s,0"`,
_W_negative_sign: [^]u16 `fmt:"s,0"`,
_W_decimal_point: cstring16,
_W_thousands_sep: cstring16,
_W_int_curr_symbol: cstring16,
_W_currency_symbol: cstring16,
_W_mon_decimal_point: cstring16,
_W_mon_thousands_sep: cstring16,
_W_positive_sign: cstring16,
_W_negative_sign: cstring16,
}
} else {
lconv :: struct {
+12 -12
View File
@@ -22,7 +22,7 @@ DEFAULT_CAPACITY :: 16
/*
Initialize a `Queue` with a starting `capacity` and an `allocator`.
*/
init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator) -> runtime.Allocator_Error {
init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error {
clear(q)
q.data = transmute([dynamic]T)runtime.Raw_Dynamic_Array{
data = nil,
@@ -30,7 +30,7 @@ init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := contex
cap = 0,
allocator = allocator,
}
return reserve(q, capacity)
return reserve(q, capacity, loc)
}
/*
@@ -114,9 +114,9 @@ Reserve enough space in the queue for at least the specified capacity.
This may return an error if allocation failed.
*/
reserve :: proc(q: ^$Q/Queue($T), capacity: int) -> runtime.Allocator_Error {
reserve :: proc(q: ^$Q/Queue($T), capacity: int, loc := #caller_location) -> runtime.Allocator_Error {
if capacity > space(q^) {
return _grow(q, uint(capacity))
return _grow(q, uint(capacity), loc)
}
return nil
}
@@ -269,9 +269,9 @@ Example:
assert(queue.pop_front(&q) == 3)
}
*/
push_back :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) {
push_back :: proc(q: ^$Q/Queue($T), elem: T, loc := #caller_location) -> (ok: bool, err: runtime.Allocator_Error) {
if space(q^) == 0 {
_grow(q) or_return
_grow(q, loc = loc) or_return
}
idx := (q.offset+uint(q.len))%builtin.len(q.data)
q.data[idx] = elem
@@ -303,9 +303,9 @@ Example:
assert(queue.pop_back(&q) == 1)
}
*/
push_front :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) {
push_front :: proc(q: ^$Q/Queue($T), elem: T, loc := #caller_location) -> (ok: bool, err: runtime.Allocator_Error) {
if space(q^) == 0 {
_grow(q) or_return
_grow(q, loc = loc) or_return
}
q.offset = uint(q.offset - 1 + builtin.len(q.data)) % builtin.len(q.data)
q.len += 1
@@ -396,10 +396,10 @@ Push many elements at once to the back of the queue.
If there is not enough space left and allocation fails to get more, this will
return false with an `Allocator_Error`.
*/
push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> (ok: bool, err: runtime.Allocator_Error) {
push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T, loc := #caller_location) -> (ok: bool, err: runtime.Allocator_Error) {
n := uint(builtin.len(elems))
if space(q^) < int(n) {
_grow(q, q.len + n) or_return
_grow(q, q.len + n, loc) or_return
}
sz := uint(builtin.len(q.data))
@@ -465,10 +465,10 @@ clear :: proc(q: ^$Q/Queue($T)) {
// Internal growing procedure
_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> runtime.Allocator_Error {
_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0, loc := #caller_location) -> runtime.Allocator_Error {
new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2)
n := uint(builtin.len(q.data))
builtin.resize(&q.data, int(new_capacity)) or_return
builtin.resize(&q.data, int(new_capacity), loc) or_return
if q.offset + q.len > n {
diff := n - q.offset
copy(q.data[new_capacity-diff:], q.data[q.offset:][:diff])
+1 -1
View File
@@ -54,7 +54,7 @@ _resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> (
symbol.SizeOfStruct = size_of(symbol^)
symbol.MaxNameLen = 255
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 {
fl.procedure = fmt.aprintf("(procedure: 0x%x)", frame, allocator=allocator)
}
+1 -1
View File
@@ -13,7 +13,7 @@ _LIBRARY_FILE_EXTENSION :: "dll"
_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
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)
return handle, handle != nil
}
+7 -5
View File
@@ -82,14 +82,16 @@ _tag_implementations_id: map[string]Tag_Implementation
_tag_implementations_type: map[typeid]Tag_Implementation
// Register a custom tag implementation to be used when marshalling that type and unmarshalling that tag number.
tag_register_type :: proc(impl: Tag_Implementation, nr: Tag_Number, type: typeid) {
tag_register_type :: proc "contextless" (impl: Tag_Implementation, nr: Tag_Number, type: typeid) {
context = runtime.default_context()
_tag_implementations_nr[nr] = impl
_tag_implementations_type[type] = impl
}
// Register a custom tag implementation to be used when marshalling that tag number or marshalling
// a field with the struct tag `cbor_tag:"nr"`.
tag_register_number :: proc(impl: Tag_Implementation, nr: Tag_Number, id: string) {
tag_register_number :: proc "contextless" (impl: Tag_Implementation, nr: Tag_Number, id: string) {
context = runtime.default_context()
_tag_implementations_nr[nr] = impl
_tag_implementations_id[id] = impl
}
@@ -98,13 +100,13 @@ tag_register_number :: proc(impl: Tag_Implementation, nr: Tag_Number, id: string
INITIALIZE_DEFAULT_TAGS :: #config(CBOR_INITIALIZE_DEFAULT_TAGS, !ODIN_DEFAULT_TO_PANIC_ALLOCATOR && !ODIN_DEFAULT_TO_NIL_ALLOCATOR)
@(private, init, disabled=!INITIALIZE_DEFAULT_TAGS)
tags_initialize_defaults :: proc() {
tags_initialize_defaults :: proc "contextless" () {
tags_register_defaults()
}
// Registers tags that have implementations provided by this package.
// This is done by default and can be controlled with the `CBOR_INITIALIZE_DEFAULT_TAGS` define.
tags_register_defaults :: proc() {
tags_register_defaults :: proc "contextless" () {
tag_register_number({nil, tag_time_unmarshal, tag_time_marshal}, TAG_EPOCH_TIME_NR, TAG_EPOCH_TIME_ID)
tag_register_number({nil, tag_base64_unmarshal, tag_base64_marshal}, TAG_BASE64_NR, TAG_BASE64_ID)
tag_register_number({nil, tag_cbor_unmarshal, tag_cbor_marshal}, TAG_CBOR_NR, TAG_CBOR_ID)
@@ -298,7 +300,7 @@ tag_base64_unmarshal :: proc(_: ^Tag_Implementation, d: Decoder, _: Tag_Number,
#partial switch t in ti.variant {
case reflect.Type_Info_String:
assert(t.encoding == .UTF_8)
if t.is_cstring {
length := base64.decoded_len(bytes)
builder := strings.builder_make(0, length+1)
+2
View File
@@ -335,6 +335,8 @@ _unmarshal_value :: proc(d: Decoder, v: any, hdr: Header, allocator := context.a
_unmarshal_bytes :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header, add: Add, allocator := context.allocator, loc := #caller_location) -> (err: Unmarshal_Error) {
#partial switch t in ti.variant {
case reflect.Type_Info_String:
assert(t.encoding == .UTF_8)
bytes := err_conv(_decode_bytes(d, add, allocator=allocator, loc=loc)) or_return
if t.is_cstring {
+4 -4
View File
@@ -353,10 +353,10 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
#partial switch info in ti.variant {
case runtime.Type_Info_String:
switch x in v {
case string:
return x == ""
case cstring:
return x == nil || x == ""
case string: return x == ""
case cstring: return x == nil || x == ""
case string16: return x == ""
case cstring16: return x == nil || x == ""
}
case runtime.Type_Info_Any:
return v.(any) == nil
+3 -1
View File
@@ -572,7 +572,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
key_ptr: rawptr
#partial switch tk in t.key.variant {
case runtime.Type_Info_String:
case runtime.Type_Info_String:
assert(tk.encoding == .UTF_8)
key_ptr = rawptr(&key)
key_cstr: cstring
if reflect.is_cstring(t.key) {
+2
View File
@@ -127,6 +127,8 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info:
}
case runtime.Type_Info_String:
assert(specific_type_info.encoding == .UTF_8)
if specific_type_info.is_cstring {
cstr_ptr := (^cstring)(ptr)
if cstr_ptr != nil {
+1 -1
View File
@@ -38,6 +38,6 @@ Note that only one can be active at a time.
Inputs:
- setter: The type setter. Pass `nil` to disable any previously set setter.
*/
register_type_setter :: proc(setter: Custom_Type_Setter) {
register_type_setter :: proc "contextless" (setter: Custom_Type_Setter) {
global_custom_type_setter = setter
}
+2 -2
View File
@@ -29,6 +29,8 @@ Integer:
%x base 16, with lower-case letters for a-f
%X base 16, with upper-case letters for A-F
%U Unicode format: U+1234; same as "U+%04X"
%m number of bytes in the best unit of measurement, e.g. 123.45mib
%M number of bytes in the best unit of measurement, e.g. 123.45MiB
Floating-point, complex numbers, and quaternions:
%e scientific notation, e.g. -1.23456e+78
%E scientific notation, e.g. -1.23456E+78
@@ -38,8 +40,6 @@ Floating-point, complex numbers, and quaternions:
%G synonym for %g
%h hexadecimal (lower-case) representation with 0h prefix (0h01234abcd)
%H hexadecimal (upper-case) representation with 0H prefix (0h01234ABCD)
%m number of bytes in the best unit of measurement, e.g. 123.45mib
%M number of bytes in the best unit of measurement, e.g. 123.45MiB
String and slice of bytes
%s the uninterpreted bytes of the string or slice
%q a double-quoted string safely escaped with Odin syntax
+84 -8
View File
@@ -1551,6 +1551,79 @@ fmt_string :: proc(fi: ^Info, s: string, verb: rune) {
fmt_cstring :: proc(fi: ^Info, s: cstring, verb: rune) {
fmt_string(fi, string(s), verb)
}
// Formats a string UTF-16 with a specific format.
//
// Inputs:
// - fi: Pointer to the Info struct containing format settings.
// - s: The string to format.
// - verb: The format specifier character (e.g. 's', 'v', 'q', 'x', 'X').
//
fmt_string16 :: proc(fi: ^Info, s: string16, verb: rune) {
s, verb := s, verb
if ol, ok := fi.optional_len.?; ok {
s = s[:clamp(ol, 0, len(s))]
}
if !fi.in_bad && fi.record_level > 0 && verb == 'v' {
verb = 'q'
}
switch verb {
case 's', 'v':
if fi.width_set {
if fi.width > len(s) {
if fi.minus {
io.write_string16(fi.writer, s, &fi.n)
}
for _ in 0..<fi.width - len(s) {
io.write_byte(fi.writer, ' ', &fi.n)
}
if !fi.minus {
io.write_string16(fi.writer, s, &fi.n)
}
} else {
io.write_string16(fi.writer, s, &fi.n)
}
} else {
io.write_string16(fi.writer, s, &fi.n)
}
case 'q', 'w': // quoted string
io.write_quoted_string16(fi.writer, s, '"', &fi.n)
case 'x', 'X':
space := fi.space
fi.space = false
defer fi.space = space
for i in 0..<len(s) {
if i > 0 && space {
io.write_byte(fi.writer, ' ', &fi.n)
}
char_set := __DIGITS_UPPER
if verb == 'x' {
char_set = __DIGITS_LOWER
}
_fmt_int(fi, u64(s[i]), 16, false, bit_size=16, digits=char_set)
}
case:
fmt_bad_verb(fi, verb)
}
}
// Formats a C-style UTF-16 string with a specific format.
//
// Inputs:
// - fi: Pointer to the Info struct containing format settings.
// - s: The C-style string to format.
// - verb: The format specifier character (Ref fmt_string).
//
fmt_cstring16 :: proc(fi: ^Info, s: cstring16, verb: rune) {
fmt_string16(fi, string16(s), verb)
}
// Formats a raw pointer with a specific format.
//
// Inputs:
@@ -2273,14 +2346,14 @@ fmt_array :: proc(fi: ^Info, data: rawptr, n: int, elem_size: int, elem: ^reflec
}
switch reflect.type_info_base(elem).id {
case byte: fmt_string(fi, string(([^]byte)(data)[:n]), verb); return
case u16: print_utf16(fi, ([^]u16)(data)[:n]); return
case u16le: print_utf16(fi, ([^]u16le)(data)[:n]); return
case u16be: print_utf16(fi, ([^]u16be)(data)[:n]); return
case u32: print_utf32(fi, ([^]u32)(data)[:n]); return
case u32le: print_utf32(fi, ([^]u32le)(data)[:n]); return
case u32be: print_utf32(fi, ([^]u32be)(data)[:n]); return
case rune: print_utf32(fi, ([^]rune)(data)[:n]); return
case byte: fmt_string(fi, string (([^]byte)(data)[:n]), verb); return
case u16: fmt_string16(fi, string16(([^]u16) (data)[:n]), verb); return
case u16le: print_utf16(fi, ([^]u16le)(data)[:n]); return
case u16be: print_utf16(fi, ([^]u16be)(data)[:n]); return
case u32: print_utf32(fi, ([^]u32)(data)[:n]); return
case u32le: print_utf32(fi, ([^]u32le)(data)[:n]); return
case u32be: print_utf32(fi, ([^]u32be)(data)[:n]); return
case rune: print_utf32(fi, ([^]rune)(data)[:n]); return
}
}
if verb == 'p' {
@@ -3210,6 +3283,9 @@ fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) {
case string: fmt_string(fi, a, verb)
case cstring: fmt_cstring(fi, a, verb)
case string16: fmt_string16(fi, a, verb)
case cstring16: fmt_cstring16(fi, a, verb)
case typeid: reflect.write_typeid(fi.writer, a, &fi.n)
case i16le: fmt_int(fi, u64(a), true, 16, verb)
+1 -1
View File
@@ -741,6 +741,6 @@ destroy :: proc(img: ^Image) {
}
@(init, private)
_register :: proc() {
_register :: proc "contextless" () {
image.register(.BMP, load_from_bytes, destroy)
}
+5 -5
View File
@@ -10,13 +10,13 @@ Destroy_Proc :: #type proc(img: ^Image)
_internal_loaders: [Which_File_Type]Loader_Proc
_internal_destroyers: [Which_File_Type]Destroy_Proc
register :: proc(kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) {
assert(loader != nil)
assert(destroyer != nil)
assert(_internal_loaders[kind] == nil)
register :: proc "contextless" (kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) {
assert_contextless(loader != nil)
assert_contextless(destroyer != nil)
assert_contextless(_internal_loaders[kind] == nil)
_internal_loaders[kind] = loader
assert(_internal_destroyers[kind] == nil)
assert_contextless(_internal_destroyers[kind] == nil)
_internal_destroyers[kind] = destroyer
}
+1 -1
View File
@@ -720,7 +720,7 @@ autoselect_pbm_format_from_image :: proc(img: ^Image, prefer_binary := true, for
}
@(init, private)
_register :: proc() {
_register :: proc "contextless" () {
loader :: proc(data: []byte, options: image.Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) {
return load_from_bytes(data, allocator)
}
+1 -1
View File
@@ -1611,6 +1611,6 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
}
@(init, private)
_register :: proc() {
_register :: proc "contextless" () {
image.register(.PNG, load_from_bytes, destroy)
}
+1 -1
View File
@@ -371,6 +371,6 @@ qoi_hash :: #force_inline proc(pixel: RGBA_Pixel) -> (index: u8) {
}
@(init, private)
_register :: proc() {
_register :: proc "contextless" () {
image.register(.QOI, load_from_bytes, destroy)
}
+1 -1
View File
@@ -406,6 +406,6 @@ IMAGE_DESCRIPTOR_RIGHT_MASK :: 1<<4
IMAGE_DESCRIPTOR_TOP_MASK :: 1<<5
@(init, private)
_register :: proc() {
_register :: proc "contextless" () {
image.register(.TGA, load_from_bytes, destroy)
}
+24
View File
@@ -5,6 +5,7 @@ package io
import "base:intrinsics"
import "core:unicode/utf8"
import "core:unicode/utf16"
// Seek whence values
Seek_From :: enum {
@@ -314,6 +315,29 @@ write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int,
return write(s, transmute([]byte)str, n_written)
}
// write_string16 writes the contents of the string16 s to w reencoded as utf-8
write_string16 :: proc(s: Writer, str: string16, n_written: ^int = nil) -> (n: int, err: Error) {
for i := 0; i < len(str); i += 1 {
r := rune(utf16.REPLACEMENT_CHAR)
switch c := str[i]; {
case c < utf16._surr1, utf16._surr3 <= c:
r = rune(c)
case utf16._surr1 <= c && c < utf16._surr2 && i+1 < len(str) &&
utf16._surr2 <= str[i+1] && str[i+1] < utf16._surr3:
r = utf16.decode_surrogate_pair(rune(c), rune(str[i+1]))
i += 1
}
w: int
w, err = write_rune(s, r, n_written)
n += w
if err != nil {
return
}
}
return
}
// write_rune writes a UTF-8 encoded rune to w.
write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err: Error) {
defer if err == nil && n_written != nil {
+27
View File
@@ -264,6 +264,33 @@ write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written
return
}
write_quoted_string16 :: proc(w: Writer, str: string16, quote: byte = '"', n_written: ^int = nil, for_json := false) -> (n: int, err: Error) {
defer if n_written != nil {
n_written^ += n
}
write_byte(w, quote, &n) or_return
for width, s := 0, str; len(s) > 0; s = s[width:] {
r := rune(s[0])
width = 1
if r >= utf8.RUNE_SELF {
r, width = utf16.decode_rune_in_string(s)
}
if width == 1 && r == utf8.RUNE_ERROR {
write_byte(w, '\\', &n) or_return
write_byte(w, 'x', &n) or_return
write_byte(w, DIGITS_LOWER[s[0]>>4], &n) or_return
write_byte(w, DIGITS_LOWER[s[0]&0xf], &n) or_return
continue
}
n_wrapper(write_escaped_rune(w, r, quote, false, nil, for_json), &n) or_return
}
write_byte(w, quote, &n) or_return
return
}
// writer append a quoted rune into the byte buffer, return the written size
write_quoted_rune :: proc(w: Writer, r: rune) -> (n: int) {
_write_byte :: #force_inline proc(w: Writer, c: byte) -> int {
+3 -1
View File
@@ -43,12 +43,14 @@ File_Console_Logger_Data :: struct {
@(private) global_subtract_stderr_options: Options
@(init, private)
init_standard_stream_status :: proc() {
init_standard_stream_status :: proc "contextless" () {
// NOTE(Feoramund): While it is technically possible for these streams to
// be redirected during the runtime of the program, the cost of checking on
// every single log message is not worth it to support such an
// uncommonly-used feature.
if terminal.color_enabled {
context = runtime.default_context()
// This is done this way because it's possible that only one of these
// streams could be redirected to a file.
if !terminal.is_terminal(os.stdout) {
+10 -8
View File
@@ -7,6 +7,7 @@
package math_big
import "base:intrinsics"
import "base:runtime"
import rnd "core:math/rand"
/*
@@ -778,22 +779,23 @@ int_from_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, alloca
INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
@(init, private)
_init_constants :: proc() {
_init_constants :: proc "contextless" () {
initialize_constants()
}
initialize_constants :: proc() -> (res: int) {
internal_set( INT_ZERO, 0); INT_ZERO.flags = {.Immutable}
internal_set( INT_ONE, 1); INT_ONE.flags = {.Immutable}
internal_set(INT_MINUS_ONE, -1); INT_MINUS_ONE.flags = {.Immutable}
initialize_constants :: proc "contextless" () -> (res: int) {
context = runtime.default_context()
internal_int_set_from_integer( INT_ZERO, 0); INT_ZERO.flags = {.Immutable}
internal_int_set_from_integer( INT_ONE, 1); INT_ONE.flags = {.Immutable}
internal_int_set_from_integer(INT_MINUS_ONE, -1); INT_MINUS_ONE.flags = {.Immutable}
/*
We set these special values to -1 or 1 so they don't get mistake for zero accidentally.
This allows for shortcut tests of is_zero as .used == 0.
*/
internal_set( INT_NAN, 1); INT_NAN.flags = {.Immutable, .NaN}
internal_set( INT_INF, 1); INT_INF.flags = {.Immutable, .Inf}
internal_set(INT_MINUS_INF, -1); INT_MINUS_INF.flags = {.Immutable, .Inf}
internal_int_set_from_integer( INT_NAN, 1); INT_NAN.flags = {.Immutable, .NaN}
internal_int_set_from_integer( INT_INF, 1); INT_INF.flags = {.Immutable, .Inf}
internal_int_set_from_integer(INT_MINUS_INF, -1); INT_MINUS_INF.flags = {.Immutable, .Inf}
return _DEFAULT_MUL_KARATSUBA_CUTOFF
}
+5 -5
View File
@@ -27,10 +27,10 @@
package math_big
import "core:mem"
import "base:intrinsics"
import rnd "core:math/rand"
import "base:builtin"
import "base:intrinsics"
import "core:mem"
import rnd "core:math/rand"
/*
Low-level addition, unsigned. Handbook of Applied Cryptography, algorithm 14.7.
@@ -2885,12 +2885,12 @@ internal_clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context
}
internal_clear_if_uninitialized :: proc {internal_clear_if_uninitialized_single, internal_clear_if_uninitialized_multi, }
internal_error_if_immutable_single :: proc(arg: ^Int) -> (err: Error) {
internal_error_if_immutable_single :: proc "contextless" (arg: ^Int) -> (err: Error) {
if arg != nil && .Immutable in arg.flags { return .Assignment_To_Immutable }
return nil
}
internal_error_if_immutable_multi :: proc(args: ..^Int) -> (err: Error) {
internal_error_if_immutable_multi :: proc "contextless" (args: ..^Int) -> (err: Error) {
for i in args {
if i != nil && .Immutable in i.flags { return .Assignment_To_Immutable }
}
+18 -31
View File
@@ -56,13 +56,6 @@ query_info :: proc(gen := context.random_generator) -> Generator_Query_Info {
}
@(private)
_random_u64 :: proc(gen := context.random_generator) -> (res: u64) {
ok := runtime.random_generator_read_ptr(gen, &res, size_of(res))
assert(ok, "uninitialized gen/context.random_generator")
return
}
/*
Generates a random 32 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -84,7 +77,7 @@ Possible Output:
*/
@(require_results)
uint32 :: proc(gen := context.random_generator) -> (val: u32) { return u32(_random_u64(gen)) }
uint32 :: proc(gen := context.random_generator) -> (val: u32) {return u32(uint64(gen))}
/*
Generates a random 64 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -107,7 +100,11 @@ Possible Output:
*/
@(require_results)
uint64 :: proc(gen := context.random_generator) -> (val: u64) { return _random_u64(gen) }
uint64 :: proc(gen := context.random_generator) -> (val: u64) {
ok := runtime.random_generator_read_ptr(gen, &val, size_of(val))
assert(ok, "uninitialized gen/context.random_generator")
return
}
/*
Generates a random 128 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -131,13 +128,13 @@ Possible Output:
*/
@(require_results)
uint128 :: proc(gen := context.random_generator) -> (val: u128) {
a := u128(_random_u64(gen))
b := u128(_random_u64(gen))
a := u128(uint64(gen))
b := u128(uint64(gen))
return (a<<64) | b
}
/*
Generates a random 31 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random 31 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
The sign bit will always be set to 0, thus all generated numbers will be positive.
Returns:
@@ -160,7 +157,7 @@ Possible Output:
@(require_results) int31 :: proc(gen := context.random_generator) -> (val: i32) { return i32(uint32(gen) << 1 >> 1) }
/*
Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
The sign bit will always be set to 0, thus all generated numbers will be positive.
Returns:
@@ -183,7 +180,7 @@ Possible Output:
@(require_results) int63 :: proc(gen := context.random_generator) -> (val: i64) { return i64(uint64(gen) << 1 >> 1) }
/*
Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
The sign bit will always be set to 0, thus all generated numbers will be positive.
Returns:
@@ -480,8 +477,8 @@ Possible Output:
}
/*
Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used.
Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value.
Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used.
Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value.
Inputs:
- p: The byte slice to fill
@@ -508,22 +505,12 @@ Possible Output:
*/
@(require_results)
read :: proc(p: []byte, gen := context.random_generator) -> (n: int) {
pos := i8(0)
val := i64(0)
for n = 0; n < len(p); n += 1 {
if pos == 0 {
val = int63(gen)
pos = 7
}
p[n] = byte(val)
val >>= 8
pos -= 1
}
return
if !runtime.random_generator_read_bytes(gen, p) {return 0}
return len(p)
}
/*
Creates a slice of `int` filled with random values using the provided random number generator. If no generator is provided the global random number generator will be used.
Creates a slice of `int` filled with random values using the provided random number generator. If no generator is provided the global random number generator will be used.
*Allocates Using Provided Allocator*
@@ -566,7 +553,7 @@ perm :: proc(n: int, allocator := context.allocator, gen := context.random_gener
}
/*
Randomizes the ordering of elements for the provided slice. If no generator is provided the global random number generator will be used.
Randomizes the ordering of elements for the provided slice. If no generator is provided the global random number generator will be used.
Inputs:
- array: The slice to randomize
@@ -607,7 +594,7 @@ shuffle :: proc(array: $T/[]$E, gen := context.random_generator) {
}
/*
Returns a random element from the provided slice. If no generator is provided the global random number generator will be used.
Returns a random element from the provided slice. If no generator is provided the global random number generator will be used.
Inputs:
- array: The slice to choose an element from
+2 -1
View File
@@ -2331,7 +2331,7 @@ buddy_allocator_alloc_bytes_non_zeroed :: proc(b: ^Buddy_Allocator, size: uint)
}
found.is_free = false
data := ([^]byte)(found)[b.alignment:][:size]
assert(cast(uintptr)raw_data(data)+cast(uintptr)size < cast(uintptr)buddy_block_next(found), "Buddy_Allocator has made an allocation which overlaps a block header.")
assert(cast(uintptr)raw_data(data)+cast(uintptr)(size-1) < cast(uintptr)buddy_block_next(found), "Buddy_Allocator has made an allocation which overlaps a block header.")
// ensure_poisoned(data)
// sanitizer.address_unpoison(data)
return data, nil
@@ -2436,6 +2436,7 @@ compat_allocator_init :: proc(rra: ^Compat_Allocator, allocator := context.alloc
rra.parent = allocator
}
@(require_results)
compat_allocator :: proc(rra: ^Compat_Allocator) -> Allocator {
return Allocator{
data = rra,
+1 -1
View File
@@ -9,7 +9,7 @@ _ :: runtime
DEFAULT_PAGE_SIZE := uint(4096)
@(init, private)
platform_memory_init :: proc() {
platform_memory_init :: proc "contextless" () {
_platform_memory_init()
}
+2 -2
View File
@@ -43,10 +43,10 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags)
return errno == .NONE
}
_platform_memory_init :: proc() {
_platform_memory_init :: proc "contextless" () {
DEFAULT_PAGE_SIZE = 4096
// is power of two
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
assert_contextless(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
}
+1 -1
View File
@@ -25,7 +25,7 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags)
return false
}
_platform_memory_init :: proc() {
_platform_memory_init :: proc "contextless" () {
}
_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) {
+2 -2
View File
@@ -28,13 +28,13 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags)
return posix.mprotect(data, size, transmute(posix.Prot_Flags)flags) == .OK
}
_platform_memory_init :: proc() {
_platform_memory_init :: proc "contextless" () {
// NOTE: `posix.PAGESIZE` due to legacy reasons could be wrong so we use `sysconf`.
size := posix.sysconf(._PAGESIZE)
DEFAULT_PAGE_SIZE = uint(max(size, posix.PAGESIZE))
// is power of two
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
assert_contextless(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
}
_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) {
+3 -3
View File
@@ -72,7 +72,7 @@ foreign Kernel32 {
flProtect: u32,
dwMaximumSizeHigh: u32,
dwMaximumSizeLow: u32,
lpName: [^]u16,
lpName: cstring16,
) -> rawptr ---
MapViewOfFile :: proc(
@@ -146,13 +146,13 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags)
@(no_sanitize_address)
_platform_memory_init :: proc() {
_platform_memory_init :: proc "contextless" () {
sys_info: SYSTEM_INFO
GetSystemInfo(&sys_info)
DEFAULT_PAGE_SIZE = max(DEFAULT_PAGE_SIZE, uint(sys_info.dwPageSize))
// is power of two
assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
assert_contextless(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
}
+1 -1
View File
@@ -79,7 +79,7 @@ Shutdown_Manner :: enum c.int {
}
@(init, private)
ensure_winsock_initialized :: proc() {
ensure_winsock_initialized :: proc "contextless" () {
win.ensure_winsock_initialized()
}
+2 -2
View File
@@ -209,14 +209,14 @@ scan_comment :: proc(t: ^Tokenizer) -> string {
scan_file_tag :: proc(t: ^Tokenizer) -> string {
offset := t.offset - 1
for t.ch != '\n' {
for t.ch != '\n' && t.ch != utf8.RUNE_EOF {
if t.ch == '/' {
next := peek_byte(t, 0)
if next == '/' || next == '*' {
break
}
}
}
advance_rune(t)
}
+1 -1
View File
@@ -87,7 +87,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
defer delete(path)
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 {
err = get_last_error()
return dfi[:], err
+2 -2
View File
@@ -16,7 +16,7 @@ MAX_TEMP_ARENA_COLLISIONS :: MAX_TEMP_ARENA_COUNT - 1
global_default_temp_allocator_arenas: [MAX_TEMP_ARENA_COUNT]runtime.Arena
@(fini, private)
temp_allocator_fini :: proc() {
temp_allocator_fini :: proc "contextless" () {
for &arena in global_default_temp_allocator_arenas {
runtime.arena_destroy(&arena)
}
@@ -69,6 +69,6 @@ _temp_allocator_end :: proc(tmp: runtime.Arena_Temp) {
}
@(init, private)
init_thread_local_cleaner :: proc() {
init_thread_local_cleaner :: proc "contextless" () {
runtime.add_thread_local_cleaner(temp_allocator_fini)
}
+3 -11
View File
@@ -16,7 +16,7 @@ find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW, al
}
temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
path := concatenate({base_path, `\`, win32_wstring_to_utf8(raw_data(d.cFileName[:]), temp_allocator) or_else ""}, allocator) or_return
path := concatenate({base_path, `\`, win32_wstring_to_utf8(cstring16(raw_data(d.cFileName[:])), temp_allocator) or_else ""}, allocator) or_return
handle := win32.HANDLE(_open_internal(path, {.Read}, 0o666) or_else 0)
defer win32.CloseHandle(handle)
@@ -107,15 +107,7 @@ _read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) {
return
}
wpath: []u16
{
i := 0
for impl.wname[i] != 0 {
i += 1
}
wpath = impl.wname[:i]
}
wpath := string16(impl.wname)
temp_allocator := TEMP_ALLOCATOR_GUARD({})
wpath_search := make([]u16, len(wpath)+3, temp_allocator)
@@ -124,7 +116,7 @@ _read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) {
wpath_search[len(wpath)+1] = '*'
wpath_search[len(wpath)+2] = 0
it.impl.find_handle = win32.FindFirstFileW(raw_data(wpath_search), &it.impl.find_data)
it.impl.find_handle = win32.FindFirstFileW(cstring16(raw_data(wpath_search)), &it.impl.find_data)
if it.impl.find_handle == win32.INVALID_HANDLE_VALUE {
read_directory_iterator_set_error(it, impl.name, _get_platform_error())
return
+1 -1
View File
@@ -31,7 +31,7 @@ _lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value:
return "", false
}
value = win32_utf16_to_utf8(b[:n], allocator) or_else ""
value = win32_utf16_to_utf8(string16(b[:n]), allocator) or_else ""
found = true
return
}
+2 -2
View File
@@ -45,8 +45,8 @@ _stderr := File{
}
@init
_standard_stream_init :: proc() {
new_std :: proc(impl: ^File_Impl, fd: linux.Fd, name: string) -> ^File {
_standard_stream_init :: proc "contextless" () {
new_std :: proc "contextless" (impl: ^File_Impl, fd: linux.Fd, name: string) -> ^File {
impl.file.impl = impl
impl.fd = linux.Fd(fd)
impl.allocator = runtime.nil_allocator()
+2 -2
View File
@@ -25,8 +25,8 @@ File_Impl :: struct {
}
@(init)
init_std_files :: proc() {
new_std :: proc(impl: ^File_Impl, fd: posix.FD, name: cstring) -> ^File {
init_std_files :: proc "contextless" () {
new_std :: proc "contextless" (impl: ^File_Impl, fd: posix.FD, name: cstring) -> ^File {
impl.file.impl = impl
impl.fd = fd
impl.allocator = runtime.nil_allocator()
+1 -1
View File
@@ -151,7 +151,7 @@ read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator) -> (d
n: int
n, err = read(f, buffer[:])
total += n
append_elems(&out_buffer, ..buffer[:n])
append_elems(&out_buffer, ..buffer[:n]) or_return
if err != nil {
if err == .EOF || err == .Broken_Pipe {
err = nil
+2 -2
View File
@@ -30,8 +30,8 @@ Preopen :: struct {
preopens: []Preopen
@(init)
init_std_files :: proc() {
new_std :: proc(impl: ^File_Impl, fd: wasi.fd_t, name: string) -> ^File {
init_std_files :: proc "contextless" () {
new_std :: proc "contextless" (impl: ^File_Impl, fd: wasi.fd_t, name: string) -> ^File {
impl.file.impl = impl
impl.allocator = runtime.nil_allocator()
impl.fd = fd
+58 -22
View File
@@ -43,8 +43,8 @@ File_Impl :: struct {
}
@(init)
init_std_files :: proc() {
new_std :: proc(impl: ^File_Impl, code: u32, name: string) -> ^File {
init_std_files :: proc "contextless" () {
new_std :: proc "contextless" (impl: ^File_Impl, code: u32, name: string) -> ^File {
impl.file.impl = impl
impl.allocator = runtime.nil_allocator()
@@ -77,7 +77,7 @@ init_std_files :: proc() {
stderr = new_std(&files[2], win32.STD_ERROR_HANDLE, "<stderr>")
}
_handle :: proc(f: ^File) -> win32.HANDLE {
_handle :: proc "contextless" (f: ^File) -> win32.HANDLE {
return win32.HANDLE(_fd(f))
}
@@ -234,7 +234,7 @@ _clone :: proc(f: ^File) -> (clone: ^File, err: Error) {
return _new_file(uintptr(clonefd), name(f), file_allocator())
}
_fd :: proc(f: ^File) -> uintptr {
_fd :: proc "contextless" (f: ^File) -> uintptr {
if f == nil || f.impl == nil {
return INVALID_HANDLE
}
@@ -247,7 +247,7 @@ _destroy :: proc(f: ^File_Impl) -> Error {
}
a := f.allocator
err0 := free(f.wname, a)
err0 := free(rawptr(f.wname), a)
err1 := delete(f.name, a)
err2 := delete(f.r_buf, a)
err3 := delete(f.w_buf, a)
@@ -619,7 +619,7 @@ _symlink :: proc(old_name, new_name: string) -> Error {
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 |= win32.FILE_FLAG_OPEN_REPARSE_POINT
handle = win32.CreateFileW(p, 0, 0, nil, win32.OPEN_EXISTING, attrs, nil)
@@ -661,7 +661,7 @@ _normalize_link_path :: proc(p: []u16, allocator: runtime.Allocator) -> (str: st
}
handle := _open_sym_link(raw_data(p)) or_return
handle := _open_sym_link(cstring16(raw_data(p))) or_return
defer win32.CloseHandle(handle)
n := win32.GetFinalPathNameByHandleW(handle, nil, 0, win32.VOLUME_NAME_DOS)
@@ -672,7 +672,7 @@ _normalize_link_path :: proc(p: []u16, allocator: runtime.Allocator) -> (str: st
temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
buf := make([]u16, n+1, temp_allocator)
n = win32.GetFinalPathNameByHandleW(handle, raw_data(buf), u32(len(buf)), win32.VOLUME_NAME_DOS)
n = win32.GetFinalPathNameByHandleW(handle, cstring16(raw_data(buf)), u32(len(buf)), win32.VOLUME_NAME_DOS)
if n == 0 {
return "", _get_platform_error()
}
@@ -713,7 +713,7 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er
switch rdb.ReparseTag {
case win32.IO_REPARSE_TAG_SYMLINK:
rb := (^win32.SYMBOLIC_LINK_REPARSE_BUFFER)(&rdb.rest)
pb := win32.wstring(&rb.PathBuffer)
pb := ([^]u16)(&rb.PathBuffer)
pb[rb.SubstituteNameOffset+rb.SubstituteNameLength] = 0
p := pb[rb.SubstituteNameOffset:][:rb.SubstituteNameLength]
if rb.Flags & win32.SYMLINK_FLAG_RELATIVE != 0 {
@@ -723,7 +723,7 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er
case win32.IO_REPARSE_TAG_MOUNT_POINT:
rb := (^win32.MOUNT_POINT_REPARSE_BUFFER)(&rdb.rest)
pb := win32.wstring(&rb.PathBuffer)
pb := ([^]u16)(&rb.PathBuffer)
pb[rb.SubstituteNameOffset+rb.SubstituteNameLength] = 0
p := pb[rb.SubstituteNameOffset:][:rb.SubstituteNameLength]
return _normalize_link_path(p, allocator)
@@ -874,8 +874,8 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte,
@(private="package", require_results)
win32_utf8_to_wstring :: proc(s: string, allocator: runtime.Allocator) -> (ws: [^]u16, err: runtime.Allocator_Error) {
ws = raw_data(win32_utf8_to_utf16(s, allocator) or_return)
win32_utf8_to_wstring :: proc(s: string, allocator: runtime.Allocator) -> (ws: cstring16, err: runtime.Allocator_Error) {
ws = cstring16(raw_data(win32_utf8_to_utf16(s, allocator) or_return))
return
}
@@ -909,24 +909,26 @@ win32_utf8_to_utf16 :: proc(s: string, allocator: runtime.Allocator) -> (ws: []u
}
@(private="package", require_results)
win32_wstring_to_utf8 :: proc(s: [^]u16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) {
if s == nil || s[0] == 0 {
win32_wstring_to_utf8 :: proc(s: cstring16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) {
if s == nil || s == "" {
return "", nil
}
n := 0
for s[n] != 0 {
n += 1
}
return win32_utf16_to_utf8(s[:n], allocator)
return win32_utf16_to_utf8(string16(s), allocator)
}
@(private="package")
win32_utf16_to_utf8 :: proc{
win32_utf16_string16_to_utf8,
win32_utf16_u16_to_utf8,
}
@(private="package", require_results)
win32_utf16_to_utf8 :: proc(s: []u16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) {
win32_utf16_string16_to_utf8 :: proc(s: string16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) {
if len(s) == 0 {
return
}
n := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, raw_data(s), i32(len(s)), nil, 0, nil, nil)
n := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), nil, 0, nil, nil)
if n == 0 {
return
}
@@ -938,7 +940,41 @@ win32_utf16_to_utf8 :: proc(s: []u16, allocator: runtime.Allocator) -> (res: str
// will not be null terminated.
text := make([]byte, n, allocator) or_return
n1 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, raw_data(s), i32(len(s)), raw_data(text), n, nil, nil)
n1 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), raw_data(text), n, nil, nil)
if n1 == 0 {
delete(text, allocator)
return
}
for i in 0..<n {
if text[i] == 0 {
n = i
break
}
}
res = string(text[:n])
return
}
@(private="package", require_results)
win32_utf16_u16_to_utf8 :: proc(s: []u16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) {
if len(s) == 0 {
return
}
n := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), nil, 0, nil, nil)
if n == 0 {
return
}
// If N < 0 the call to WideCharToMultiByte assume the wide string is null terminated
// and will scan it to find the first null terminated character. The resulting string will
// also be null terminated.
// If N > 0 it assumes the wide string is not null terminated and the resulting string
// will not be null terminated.
text := make([]byte, n, allocator) or_return
n1 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), raw_data(text), n, nil, nil)
if n1 == 0 {
delete(text, allocator)
return
+5 -5
View File
@@ -91,11 +91,11 @@ _remove_all :: proc(path: string) -> Error {
nil,
win32.FO_DELETE,
dir,
&empty[0],
cstring16(&empty[0]),
win32.FOF_NOCONFIRMATION | win32.FOF_NOERRORUI | win32.FOF_SILENT,
false,
nil,
&empty[0],
cstring16(&empty[0]),
}
res := win32.SHFileOperationW(&file_op)
if res != 0 {
@@ -160,7 +160,7 @@ _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err
can_use_long_paths: bool
@(init)
init_long_path_support :: proc() {
init_long_path_support :: proc "contextless" () {
can_use_long_paths = false
key: win32.HKEY
@@ -303,13 +303,13 @@ _get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absol
}
temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
rel_utf16 := win32.utf8_to_utf16(rel, temp_allocator)
n := win32.GetFullPathNameW(raw_data(rel_utf16), 0, nil, nil)
n := win32.GetFullPathNameW(cstring16(raw_data(rel_utf16)), 0, nil, nil)
if n == 0 {
return "", Platform_Error(win32.GetLastError())
}
buf := make([]u16, n, temp_allocator) or_return
n = win32.GetFullPathNameW(raw_data(rel_utf16), u32(n), raw_data(buf), nil)
n = win32.GetFullPathNameW(cstring16(raw_data(rel_utf16)), u32(n), cstring16(raw_data(buf)), nil)
if n == 0 {
return "", Platform_Error(win32.GetLastError())
}
+8 -1
View File
@@ -16,7 +16,8 @@ Arguments to the current process.
args := get_args()
@(private="file")
get_args :: proc() -> []string {
get_args :: proc "contextless" () -> []string {
context = runtime.default_context()
result := make([]string, len(runtime.args__), heap_allocator())
for rt_arg, i in runtime.args__ {
result[i] = string(rt_arg)
@@ -24,6 +25,12 @@ get_args :: proc() -> []string {
return result
}
@(fini, private="file")
delete_args :: proc "contextless" () {
context = runtime.default_context()
delete(args, heap_allocator())
}
/*
Exit the current process.
*/
+1 -1
View File
@@ -13,7 +13,7 @@ import "core:time"
foreign import lib "system:System"
foreign lib {
sysctl :: proc(
sysctl :: proc "c" (
name: [^]i32, namelen: u32,
oldp: rawptr, oldlenp: ^uint,
newp: rawptr, newlen: uint,
+4 -4
View File
@@ -175,7 +175,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
info.fields += {.Command_Line}
}
if .Command_Args in selection {
info.command_args = _parse_command_line(raw_data(cmdline_w), allocator) or_return
info.command_args = _parse_command_line(cstring16(raw_data(cmdline_w)), allocator) or_return
info.fields += {.Command_Args}
}
}
@@ -286,7 +286,7 @@ _process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields
info.fields += {.Command_Line}
}
if .Command_Args in selection {
info.command_args = _parse_command_line(raw_data(cmdline_w), allocator) or_return
info.command_args = _parse_command_line(cstring16(raw_data(cmdline_w)), allocator) or_return
info.fields += {.Command_Args}
}
}
@@ -610,7 +610,7 @@ _process_exe_by_pid :: proc(pid: int, allocator: runtime.Allocator) -> (exe_path
err =_get_platform_error()
return
}
return win32_wstring_to_utf8(raw_data(entry.szExePath[:]), allocator)
return win32_wstring_to_utf8(cstring16(raw_data(entry.szExePath[:])), allocator)
}
_get_process_user :: proc(process_handle: win32.HANDLE, allocator: runtime.Allocator) -> (full_username: string, err: Error) {
@@ -650,7 +650,7 @@ _get_process_user :: proc(process_handle: win32.HANDLE, allocator: runtime.Alloc
return strings.concatenate({domain, "\\", username}, allocator)
}
_parse_command_line :: proc(cmd_line_w: [^]u16, allocator: runtime.Allocator) -> (argv: []string, err: Error) {
_parse_command_line :: proc(cmd_line_w: cstring16, allocator: runtime.Allocator) -> (argv: []string, err: Error) {
argc: i32
argv_w := win32.CommandLineToArgvW(cmd_line_w, &argc)
if argv_w == nil {
+7 -7
View File
@@ -49,12 +49,12 @@ full_path_from_name :: proc(name: string, allocator: runtime.Allocator) -> (path
p := win32_utf8_to_utf16(name, temp_allocator) or_return
n := win32.GetFullPathNameW(raw_data(p), 0, nil, nil)
n := win32.GetFullPathNameW(cstring16(raw_data(p)), 0, nil, nil)
if n == 0 {
return "", _get_platform_error()
}
buf := make([]u16, n+1, temp_allocator)
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 {
return "", _get_platform_error()
}
@@ -140,8 +140,8 @@ _cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (strin
temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
buf := make([]u16, max(n, 260)+1, temp_allocator)
n = win32.GetFinalPathNameByHandleW(h, raw_data(buf), u32(len(buf)), 0)
return _cleanpath_from_buf(buf[:n], allocator)
n = win32.GetFinalPathNameByHandleW(h, cstring16(raw_data(buf)), u32(len(buf)), 0)
return _cleanpath_from_buf(string16(buf[:n]), allocator)
}
_cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) {
@@ -158,12 +158,12 @@ _cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
buf := make([]u16, max(n, 260)+1, temp_allocator)
n = win32.GetFinalPathNameByHandleW(h, raw_data(buf), u32(len(buf)), 0)
n = win32.GetFinalPathNameByHandleW(h, cstring16(raw_data(buf)), u32(len(buf)), 0)
return _cleanpath_strip_prefix(buf[:n]), nil
}
_cleanpath_from_buf :: proc(buf: []u16, allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) {
buf := buf
_cleanpath_from_buf :: proc(buf: string16, allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) {
buf := transmute([]u16)buf
buf = _cleanpath_strip_prefix(buf)
return win32_utf16_to_utf8(buf, allocator)
}
+2 -2
View File
@@ -12,12 +12,12 @@ _temp_dir :: proc(allocator: runtime.Allocator) -> (string, runtime.Allocator_Er
temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
b := make([]u16, max(win32.MAX_PATH, n), temp_allocator)
n = win32.GetTempPathW(u32(len(b)), raw_data(b))
n = win32.GetTempPathW(u32(len(b)), cstring16(raw_data(b)))
if n == 3 && b[1] == ':' && b[2] == '\\' {
} else if n > 0 && b[n-1] == '\\' {
n -= 1
}
return win32_utf16_to_utf8(b[:n], allocator)
return win32_utf16_to_utf8(string16(b[:n]), allocator)
}
+1 -2
View File
@@ -74,6 +74,5 @@ _get_known_folder_path :: proc(rfid: win32.REFKNOWNFOLDERID, allocator: runtime.
return "", .Invalid_Path
}
dir, _ = win32.wstring_to_utf8(path_w, -1, allocator)
return
return win32_wstring_to_utf8(cstring16(path_w), allocator)
}
+4 -2
View File
@@ -1226,7 +1226,8 @@ _processor_core_count :: proc() -> int {
}
@(private, require_results)
_alloc_command_line_arguments :: proc() -> []string {
_alloc_command_line_arguments :: proc "contextless" () -> []string {
context = runtime.default_context()
res := make([]string, len(runtime.args__))
for _, i in res {
res[i] = string(runtime.args__[i])
@@ -1235,7 +1236,8 @@ _alloc_command_line_arguments :: proc() -> []string {
}
@(private, fini)
_delete_command_line_arguments :: proc() {
_delete_command_line_arguments :: proc "contextless" () {
context = runtime.default_context()
delete(args)
}
+4 -2
View File
@@ -965,7 +965,8 @@ _processor_core_count :: proc() -> int {
@(private, require_results)
_alloc_command_line_arguments :: proc() -> []string {
_alloc_command_line_arguments :: proc "contextless" () -> []string {
context = runtime.default_context()
res := make([]string, len(runtime.args__))
for _, i in res {
res[i] = string(runtime.args__[i])
@@ -974,6 +975,7 @@ _alloc_command_line_arguments :: proc() -> []string {
}
@(private, fini)
_delete_command_line_arguments :: proc() {
_delete_command_line_arguments :: proc "contextless" () {
context = runtime.default_context()
delete(args)
}
+4 -2
View File
@@ -317,7 +317,8 @@ file_size :: proc(fd: Handle) -> (i64, Error) {
args := _alloc_command_line_arguments()
@(private, require_results)
_alloc_command_line_arguments :: proc() -> []string {
_alloc_command_line_arguments :: proc "contextless" () -> []string {
context = runtime.default_context()
res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ {
res[i] = string(arg)
@@ -326,7 +327,8 @@ _alloc_command_line_arguments :: proc() -> []string {
}
@(private, fini)
_delete_command_line_arguments :: proc() {
_delete_command_line_arguments :: proc "contextless" () {
context = runtime.default_context()
delete(args)
}
+4 -2
View File
@@ -1098,7 +1098,8 @@ _processor_core_count :: proc() -> int {
}
@(private, require_results)
_alloc_command_line_arguments :: proc() -> []string {
_alloc_command_line_arguments :: proc "contextless" () -> []string {
context = runtime.default_context()
res := make([]string, len(runtime.args__))
for _, i in res {
res[i] = string(runtime.args__[i])
@@ -1107,7 +1108,8 @@ _alloc_command_line_arguments :: proc() -> []string {
}
@(private, fini)
_delete_command_line_arguments :: proc() {
_delete_command_line_arguments :: proc "contextless" () {
context = runtime.default_context()
delete(args)
}
+4 -2
View File
@@ -1015,7 +1015,8 @@ _processor_core_count :: proc() -> int {
}
@(private, require_results)
_alloc_command_line_arguments :: proc() -> []string {
_alloc_command_line_arguments :: proc "contextless" () -> []string {
context = runtime.default_context()
res := make([]string, len(runtime.args__))
for _, i in res {
res[i] = string(runtime.args__[i])
@@ -1024,6 +1025,7 @@ _alloc_command_line_arguments :: proc() -> []string {
}
@(private, fini)
_delete_command_line_arguments :: proc() {
_delete_command_line_arguments :: proc "contextless" () {
context = runtime.default_context()
delete(args)
}
+4 -2
View File
@@ -915,7 +915,8 @@ _processor_core_count :: proc() -> int {
}
@(private, require_results)
_alloc_command_line_arguments :: proc() -> []string {
_alloc_command_line_arguments :: proc "contextless" () -> []string {
context = runtime.default_context()
res := make([]string, len(runtime.args__))
for _, i in res {
res[i] = string(runtime.args__[i])
@@ -924,6 +925,7 @@ _alloc_command_line_arguments :: proc() -> []string {
}
@(private, fini)
_delete_command_line_arguments :: proc() {
_delete_command_line_arguments :: proc "contextless" () {
context = runtime.default_context()
delete(args)
}
+11 -8
View File
@@ -28,16 +28,18 @@ stderr: Handle = 2
args := _alloc_command_line_arguments()
@(private, require_results)
_alloc_command_line_arguments :: proc() -> (args: []string) {
args = make([]string, len(runtime.args__))
for &arg, i in args {
_alloc_command_line_arguments :: proc "contextless" () -> []string {
context = runtime.default_context()
cmd_args := make([]string, len(runtime.args__))
for &arg, i in cmd_args {
arg = string(runtime.args__[i])
}
return
return cmd_args
}
@(private, fini)
_delete_command_line_arguments :: proc() {
_delete_command_line_arguments :: proc "contextless" () {
context = runtime.default_context()
delete(args)
}
@@ -57,9 +59,8 @@ Preopen :: struct {
preopens: []Preopen
@(init, private)
init_preopens :: proc() {
strip_prefixes :: proc(path: string) -> string {
init_preopens :: proc "contextless" () {
strip_prefixes :: proc "contextless"(path: string) -> string {
path := path
loop: for len(path) > 0 {
switch {
@@ -76,6 +77,8 @@ init_preopens :: proc() {
return path
}
context = runtime.default_context()
dyn_preopens: [dynamic]Preopen
loop: for fd := wasi.fd_t(3); ; fd += 1 {
desc, err := wasi.fd_prestat_get(fd)
+4 -2
View File
@@ -194,7 +194,8 @@ current_thread_id :: proc "contextless" () -> int {
@(private, require_results)
_alloc_command_line_arguments :: proc() -> []string {
_alloc_command_line_arguments :: proc "contextless" () -> []string {
context = runtime.default_context()
arg_count: i32
arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), &arg_count)
arg_list := make([]string, int(arg_count))
@@ -216,7 +217,8 @@ _alloc_command_line_arguments :: proc() -> []string {
}
@(private, fini)
_delete_command_line_arguments :: proc() {
_delete_command_line_arguments :: proc "contextless" () {
context = runtime.default_context()
for s in args {
delete(s)
}
+2 -2
View File
@@ -17,7 +17,7 @@ full_path_from_name :: proc(name: string, allocator := context.allocator) -> (pa
buf := make([dynamic]u16, 100)
defer delete(buf)
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 {
return "", get_last_error()
}
@@ -154,7 +154,7 @@ cleanpath_from_handle_u16 :: proc(fd: Handle, allocator: runtime.Allocator) -> (
return nil, get_last_error()
}
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
}
@(private, require_results)
+2 -2
View File
@@ -61,13 +61,13 @@ temp_full_path :: proc(name: string) -> (path: string, err: os.Error) {
}
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 {
return "", os.get_last_error()
}
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 {
delete(buf)
return "", os.get_last_error()
+6 -3
View File
@@ -511,9 +511,12 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt
io.write_i64(w, i64(8*ti.size), 10, &n) or_return
case Type_Info_String:
if info.is_cstring {
io.write_string(w, "cstring", &n) or_return
} else {
io.write_string(w, "string", &n) or_return
io.write_byte(w, 'c', &n) or_return
}
io.write_string(w, "string", &n) or_return
switch info.encoding {
case .UTF_8: /**/
case .UTF_16: io.write_string(w, "16", &n) or_return
}
case Type_Info_Boolean:
switch ti.id {
@@ -0,0 +1,50 @@
package objc_Foundation
import "base:intrinsics"
@(objc_class="NSBitmapImageRep")
BitmapImageRep :: struct { using _: Object }
@(objc_type=BitmapImageRep, objc_name="alloc", objc_is_class_method=true)
BitmapImageRep_alloc :: proc "c" () -> ^BitmapImageRep {
return msgSend(^BitmapImageRep, BitmapImageRep, "alloc")
}
@(objc_type=BitmapImageRep, objc_name="initWithBitmapDataPlanes")
BitmapImageRep_initWithBitmapDataPlanes :: proc "c" (
self: ^BitmapImageRep,
bitmapDataPlanes: ^^u8,
pixelsWide: Integer,
pixelsHigh: Integer,
bitsPerSample: Integer,
samplesPerPixel: Integer,
hasAlpha: bool,
isPlanar: bool,
colorSpaceName: ^String,
bytesPerRow: Integer,
bitsPerPixel: Integer) -> ^BitmapImageRep {
return msgSend(^BitmapImageRep,
self,
"initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:",
bitmapDataPlanes,
pixelsWide,
pixelsHigh,
bitsPerSample,
samplesPerPixel,
hasAlpha,
isPlanar,
colorSpaceName,
bytesPerRow,
bitsPerPixel)
}
@(objc_type=BitmapImageRep, objc_name="bitmapData")
BitmapImageRep_bitmapData :: proc "c" (self: ^BitmapImageRep) -> rawptr {
return msgSend(rawptr, self, "bitmapData")
}
@(objc_type=BitmapImageRep, objc_name="CGImage")
BitmapImageRep_CGImage :: proc "c" (self: ^BitmapImageRep) -> rawptr {
return msgSend(rawptr, self, "CGImage")
}
+19 -2
View File
@@ -568,6 +568,15 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla
@(objc_class="CALayer")
Layer :: struct { using _: Object }
@(objc_type=Layer, objc_name="contents")
Layer_contents :: proc "c" (self: ^Layer) -> rawptr {
return msgSend(rawptr, self, "contents")
}
@(objc_type=Layer, objc_name="setContents")
Layer_setContents :: proc "c" (self: ^Layer, contents: rawptr) {
msgSend(nil, self, "setContents:", contents)
}
@(objc_type=Layer, objc_name="contentsScale")
Layer_contentsScale :: proc "c" (self: ^Layer) -> Float {
return msgSend(Float, self, "contentsScale")
@@ -654,8 +663,12 @@ Window_frame :: proc "c" (self: ^Window) -> Rect {
return msgSend(Rect, self, "frame")
}
@(objc_type=Window, objc_name="setFrame")
Window_setFrame :: proc "c" (self: ^Window, frame: Rect) {
msgSend(nil, self, "setFrame:", frame)
Window_setFrame :: proc "c" (self: ^Window, frame: Rect, display: BOOL) {
msgSend(nil, self, "setFrame:display:", frame, display)
}
@(objc_type=Window, objc_name="setFrameOrigin")
Window_setFrameOrigin :: proc "c" (self: ^Window, origin: Point) {
msgSend(nil, self, "setFrameOrigin:", origin)
}
@(objc_type=Window, objc_name="opaque")
Window_opaque :: proc "c" (self: ^Window) -> BOOL {
@@ -693,6 +706,10 @@ Window_setMovable :: proc "c" (self: ^Window, ok: BOOL) {
Window_setMovableByWindowBackground :: proc "c" (self: ^Window, ok: BOOL) {
msgSend(nil, self, "setMovableByWindowBackground:", ok)
}
@(objc_type=Window, objc_name="setAcceptsMouseMovedEvents")
Window_setAcceptsMouseMovedEvents :: proc "c" (self: ^Window, ok: BOOL) {
msgSend(nil, self, "setAcceptsMouseMovedEvents:", ok)
}
@(objc_type=Window, objc_name="setStyleMask")
Window_setStyleMask :: proc "c" (self: ^Window, style_mask: WindowStyleMask) {
msgSend(nil, self, "setStyleMask:", style_mask)
+2 -2
View File
@@ -52,7 +52,7 @@ CPU :: struct {
cpu: CPU
@(init, private)
init_cpu_features :: proc "c" () {
init_cpu_features :: proc "contextless" () {
is_set :: #force_inline proc "c" (bit: u32, value: u32) -> bool {
return (value>>bit) & 0x1 != 0
}
@@ -156,7 +156,7 @@ init_cpu_features :: proc "c" () {
_cpu_name_buf: [72]u8
@(init, private)
init_cpu_name :: proc "c" () {
init_cpu_name :: proc "contextless" () {
number_of_extended_ids, _, _, _ := cpuid(0x8000_0000, 0)
if number_of_extended_ids < 0x8000_0004 {
return
+3 -1
View File
@@ -2,11 +2,13 @@
#+build linux
package sysinfo
import "base:runtime"
import "core:sys/linux"
import "core:strings"
@(init, private)
init_cpu_features :: proc() {
init_cpu_features :: proc "contextless" () {
context = runtime.default_context()
fd, err := linux.open("/proc/cpuinfo", {})
if err != .NONE { return }
defer linux.close(fd)
+4 -1
View File
@@ -2,12 +2,15 @@
#+build linux
package sysinfo
import "base:runtime"
import "core:sys/linux"
import "core:strings"
import "core:strconv"
@(init, private)
init_cpu_core_count :: proc() {
init_cpu_core_count :: proc "contextless" () {
context = runtime.default_context()
fd, err := linux.open("/proc/cpuinfo", {})
if err != .NONE { return }
defer linux.close(fd)
+5 -5
View File
@@ -7,7 +7,7 @@ import "base:intrinsics"
import "core:sys/linux"
@(init, private)
init_cpu_features :: proc() {
init_cpu_features :: proc "contextless" () {
_features: CPU_Features
defer cpu.features = _features
@@ -81,11 +81,11 @@ init_cpu_features :: proc() {
}
err := linux.riscv_hwprobe(raw_data(pairs), len(pairs), 0, nil, {})
if err != nil {
assert(err == .ENOSYS, "unexpected error from riscv_hwprobe()")
assert_contextless(err == .ENOSYS, "unexpected error from riscv_hwprobe()")
return
}
assert(pairs[0].key == .IMA_EXT_0)
assert_contextless(pairs[0].key == .IMA_EXT_0)
exts := pairs[0].value.ima_ext_0
exts -= { .FD, .C, .V }
_features += transmute(CPU_Features)exts
@@ -97,7 +97,7 @@ init_cpu_features :: proc() {
_features += { .Misaligned_Supported }
}
} else {
assert(pairs[1].key == .CPUPERF_0)
assert_contextless(pairs[1].key == .CPUPERF_0)
if .FAST in pairs[1].value.cpu_perf_0 {
_features += { .Misaligned_Supported, .Misaligned_Fast }
} else if .UNSUPPORTED not_in pairs[1].value.cpu_perf_0 {
@@ -108,6 +108,6 @@ init_cpu_features :: proc() {
}
@(init, private)
init_cpu_name :: proc() {
init_cpu_name :: proc "contextless" () {
cpu.name = "RISCV64"
}
+4 -1
View File
@@ -2,9 +2,12 @@ package sysinfo
import sys "core:sys/windows"
import "base:intrinsics"
import "base:runtime"
@(init, private)
init_cpu_core_count :: proc() {
init_cpu_core_count :: proc "contextless" () {
context = runtime.default_context()
infos: []sys.SYSTEM_LOGICAL_PROCESSOR_INFORMATION
defer delete(infos)
+4 -2
View File
@@ -10,7 +10,9 @@ import "base:runtime"
version_string_buf: [1024]u8
@(init, private)
init_os_version :: proc () {
init_os_version :: proc "contextless" () {
context = runtime.default_context()
when ODIN_OS == .NetBSD {
os_version.platform = .NetBSD
} else {
@@ -66,7 +68,7 @@ init_os_version :: proc () {
}
@(init, private)
init_ram :: proc() {
init_ram :: proc "contextless" () {
// Retrieve RAM info using `sysctl`
mib := []i32{sys.CTL_HW, sys.HW_PHYSMEM64}
mem_size: u64
+4 -1
View File
@@ -1,5 +1,7 @@
package sysinfo
import "base:runtime"
import "core:strconv"
import "core:strings"
import "core:sys/unix"
@@ -9,7 +11,8 @@ import NS "core:sys/darwin/Foundation"
version_string_buf: [1024]u8
@(init, private)
init_platform :: proc() {
init_platform :: proc "contextless" () {
context = runtime.default_context()
ws :: strings.write_string
wi :: strings.write_int
+4 -2
View File
@@ -9,7 +9,9 @@ import "base:runtime"
version_string_buf: [1024]u8
@(init, private)
init_os_version :: proc () {
init_os_version :: proc "contextless" () {
context = runtime.default_context()
os_version.platform = .FreeBSD
kernel_version_buf: [1024]u8
@@ -68,7 +70,7 @@ init_os_version :: proc () {
}
@(init, private)
init_ram :: proc() {
init_ram :: proc "contextless" () {
// Retrieve RAM info using `sysctl`
mib := []i32{sys.CTL_HW, sys.HW_PHYSMEM}
mem_size: u64
+6 -3
View File
@@ -1,6 +1,7 @@
package sysinfo
import "base:intrinsics"
import "base:runtime"
import "core:strconv"
import "core:strings"
@@ -10,7 +11,9 @@ import "core:sys/linux"
version_string_buf: [1024]u8
@(init, private)
init_os_version :: proc () {
init_os_version :: proc "contextless" () {
context = runtime.default_context()
os_version.platform = .Linux
b := strings.builder_from_bytes(version_string_buf[:])
@@ -91,11 +94,11 @@ init_os_version :: proc () {
}
@(init, private)
init_ram :: proc() {
init_ram :: proc "contextless" () {
// Retrieve RAM info using `sysinfo`
sys_info: linux.Sys_Info
errno := linux.sysinfo(&sys_info)
assert(errno == .NONE, "Good luck to whoever's debugging this, something's seriously cucked up!")
assert_contextless(errno == .NONE, "Good luck to whoever's debugging this, something's seriously cucked up!")
ram = RAM{
total_ram = int(sys_info.totalram) * int(sys_info.mem_unit),
free_ram = int(sys_info.freeram) * int(sys_info.mem_unit),
+14 -10
View File
@@ -12,7 +12,9 @@ import "base:runtime"
version_string_buf: [1024]u8
@(init, private)
init_os_version :: proc () {
init_os_version :: proc "contextless" () {
context = runtime.default_context()
/*
NOTE(Jeroen):
`GetVersionEx` will return 6.2 for Windows 10 unless the program is manifested for Windows 10.
@@ -43,6 +45,7 @@ init_os_version :: proc () {
os_version.minor = int(osvi.dwMinorVersion)
os_version.build[0] = int(osvi.dwBuildNumber)
b := strings.builder_from_bytes(version_string_buf[:])
strings.write_string(&b, "Windows ")
@@ -259,7 +262,7 @@ init_os_version :: proc () {
}
@(init, private)
init_ram :: proc() {
init_ram :: proc "contextless" () {
state: sys.MEMORYSTATUSEX
state.dwLength = size_of(state)
@@ -276,10 +279,11 @@ init_ram :: proc() {
}
@(init, private)
init_gpu_info :: proc() {
init_gpu_info :: proc "contextless" () {
GPU_INFO_BASE :: "SYSTEM\\ControlSet001\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}\\"
context = runtime.default_context()
gpu_list: [dynamic]GPU
gpu_index: int
@@ -324,8 +328,8 @@ read_reg_string :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: string, ok
status := sys.RegGetValueW(
hkey,
&key_name_wide[0],
&val_name_wide[0],
cstring16(&key_name_wide[0]),
cstring16(&val_name_wide[0]),
sys.RRF_RT_REG_SZ,
nil,
raw_data(result_wide[:]),
@@ -359,8 +363,8 @@ read_reg_i32 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i32, ok: bool
result_size := sys.DWORD(size_of(i32))
status := sys.RegGetValueW(
hkey,
&key_name_wide[0],
&val_name_wide[0],
cstring16(&key_name_wide[0]),
cstring16(&val_name_wide[0]),
sys.RRF_RT_REG_DWORD,
nil,
&res,
@@ -386,8 +390,8 @@ read_reg_i64 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i64, ok: bool
result_size := sys.DWORD(size_of(i64))
status := sys.RegGetValueW(
hkey,
&key_name_wide[0],
&val_name_wide[0],
cstring16(&key_name_wide[0]),
cstring16(&val_name_wide[0]),
sys.RRF_RT_REG_QWORD,
nil,
&res,
+1 -1
View File
@@ -1838,7 +1838,7 @@ Clock_Id :: enum {
Bits for POSIX interval timer flags.
*/
ITimer_Flags_Bits :: enum {
ABSTIME = 1,
ABSTIME = 0,
}
/*
+1
View File
@@ -1,3 +1,4 @@
#+build linux, darwin, openbsd, freebsd, netbsd, haiku
package posix
when ODIN_OS == .Darwin {
+1 -1
View File
@@ -60,7 +60,7 @@ wctomb :: libc.wctomb
mbstowcs :: libc.mbstowcs
wcstombs :: libc.wcstombs
free :: #force_inline proc(ptr: $T) where intrinsics.type_is_pointer(T) || intrinsics.type_is_multi_pointer(T) || T == cstring {
free :: #force_inline proc "c" (ptr: $T) where intrinsics.type_is_pointer(T) || intrinsics.type_is_multi_pointer(T) || T == cstring {
libc.free(rawptr(ptr))
}
+1 -1
View File
@@ -3,7 +3,7 @@ package unix
import "base:intrinsics"
sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) {
sysctl :: proc "contextless" (mib: []i32, val: ^$T) -> (ok: bool) {
mib := mib
result_size := u64(size_of(T))
+1 -1
View File
@@ -8,7 +8,7 @@ foreign libc {
@(link_name="sysctl") _unix_sysctl :: proc(name: [^]i32, namelen: u32, oldp: rawptr, oldlenp: ^c.size_t, newp: rawptr, newlen: c.size_t) -> i32 ---
}
sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) {
sysctl :: proc "contextless" (mib: []i32, val: ^$T) -> (ok: bool) {
mib := mib
result_size := c.size_t(size_of(T))
res := _unix_sysctl(raw_data(mib), u32(len(mib)), val, &result_size, nil, 0)
+1 -1
View File
@@ -9,7 +9,7 @@ foreign libc {
@(link_name="sysctl") _unix_sysctl :: proc(name: [^]i32, namelen: u32, oldp: rawptr, oldlenp: ^c.size_t, newp: rawptr, newlen: c.size_t) -> i32 ---
}
sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) {
sysctl :: proc "contextless" (mib: []i32, val: ^$T) -> (ok: bool) {
mib := mib
result_size := c.size_t(size_of(T))
res := _unix_sysctl(raw_data(mib), u32(len(mib)), val, &result_size, nil, 0)
+20
View File
@@ -373,12 +373,32 @@ remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callba
return _remove_window_event_listener(event_kind_string[kind], user_data, callback, use_capture)
}
add_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
@(default_calling_convention="contextless")
foreign dom_lib {
@(link_name="add_document_event_listener")
_add_document_event_listener :: proc(name: string, name_code: Event_Kind, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool ---
}
return _add_document_event_listener(event_kind_string[kind], kind, user_data, callback, use_capture)
}
remove_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
@(default_calling_convention="contextless")
foreign dom_lib {
@(link_name="remove_document_event_listener")
_remove_document_event_listener :: proc(name: string, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool ---
}
return _remove_document_event_listener(event_kind_string[kind], user_data, callback, use_capture)
}
remove_event_listener_from_event :: proc(e: Event) -> bool {
from_use_capture_false: bool
from_use_capture_true: bool
if e.id == "" {
from_use_capture_false = remove_window_event_listener(e.kind, e.user_data, e.callback, false)
from_use_capture_true = remove_window_event_listener(e.kind, e.user_data, e.callback, true)
from_use_capture_false |= remove_document_event_listener(e.kind, e.user_data, e.callback, false)
from_use_capture_true |= remove_document_event_listener(e.kind, e.user_data, e.callback, true)
} else {
from_use_capture_false = remove_event_listener(e.id, e.kind, e.user_data, e.callback, false)
from_use_capture_true = remove_event_listener(e.id, e.kind, e.user_data, e.callback, true)
+8
View File
@@ -275,6 +275,14 @@ remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callba
panic("vendor:wasm/js not supported on non JS targets")
}
add_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
panic("vendor:wasm/js not supported on non JS targets")
}
remove_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
panic("vendor:wasm/js not supported on non JS targets")
}
remove_event_listener_from_event :: proc(e: Event) -> bool {
panic("vendor:wasm/js not supported on non JS targets")
}
+73
View File
@@ -392,6 +392,9 @@ class WebGLInterface {
BindTexture: (target, texture) => {
this.ctx.bindTexture(target, texture ? this.textures[texture] : null)
},
BindRenderbuffer: (target, renderbuffer) => {
this.ctx.bindRenderbuffer(target, renderbuffer ? this.renderbuffers[renderbuffer] : null)
},
BlendColor: (red, green, blue, alpha) => {
this.ctx.blendColor(red, green, blue, alpha);
},
@@ -809,6 +812,40 @@ class WebGLInterface {
Uniform3i: (location, v0, v1, v2) => { this.ctx.uniform3i(this.uniforms[location], v0, v1, v2); },
Uniform4i: (location, v0, v1, v2, v3) => { this.ctx.uniform4i(this.uniforms[location], v0, v1, v2, v3); },
Uniform1fv: (location, count, addr) => {
let array = this.mem.loadF32Array(addr, 1*count);
this.ctx.uniform1fv(this.uniforms[location], array);
},
Uniform2fv: (location, count, addr) => {
let array = this.mem.loadF32Array(addr, 2*count);
this.ctx.uniform2fv(this.uniforms[location], array);
},
Uniform3fv: (location, count, addr) => {
let array = this.mem.loadF32Array(addr, 3*count);
this.ctx.uniform3fv(this.uniforms[location], array);
},
Uniform4fv: (location, count, addr) => {
let array = this.mem.loadF32Array(addr, 4*count);
this.ctx.uniform4fv(this.uniforms[location], array);
},
Uniform1iv: (location, count, addr) => {
let array = this.mem.loadI32Array(addr, 1*count);
this.ctx.uniform1iv(this.uniforms[location], array);
},
Uniform2iv: (location, count, addr) => {
let array = this.mem.loadI32Array(addr, 2*count);
this.ctx.uniform2iv(this.uniforms[location], array);
},
Uniform3iv: (location, count, addr) => {
let array = this.mem.loadI32Array(addr, 3*count);
this.ctx.uniform3iv(this.uniforms[location], array);
},
Uniform4iv: (location, count, addr) => {
let array = this.mem.loadI32Array(addr, 4*count);
this.ctx.uniform4iv(this.uniforms[location], array);
},
UniformMatrix2fv: (location, addr) => {
let array = this.mem.loadF32Array(addr, 2*2);
this.ctx.uniformMatrix2fv(this.uniforms[location], false, array);
@@ -1701,6 +1738,28 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
return true;
},
add_document_event_listener: (name_ptr, name_len, name_code, data, callback, use_capture) => {
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
let element = document;
let key = listener_key('document', name, data, callback, !!use_capture);
if (wasmMemoryInterface.listenerMap.has(key)) {
return false;
}
let listener = (e) => {
let event_data = {};
event_data.id_ptr = 0;
event_data.id_len = 0;
event_data.event = e;
event_data.name_code = name_code;
onEventReceived(event_data, data, callback);
};
wasmMemoryInterface.listenerMap.set(key, listener);
element.addEventListener(name, listener, !!use_capture);
return true;
},
remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback, use_capture) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
@@ -1733,6 +1792,20 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
element.removeEventListener(name, listener, !!use_capture);
return true;
},
remove_document_event_listener: (name_ptr, name_len, data, callback, use_capture) => {
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
let element = document;
let key = listener_key('document', name, data, callback, !!use_capture);
let listener = wasmMemoryInterface.listenerMap.get(key);
if (listener === undefined) {
return false;
}
wasmMemoryInterface.listenerMap.delete(key);
element.removeEventListener(name, listener, !!use_capture);
return true;
},
event_stop_propagation: () => {
if (event_temp.data && event_temp.data.event) {
+5 -5
View File
@@ -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))
}
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 {
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 {
return SendMessageW(hwnd, BCM_GETNOTELENGTH, 0, 0)
@@ -604,10 +604,10 @@ EDITBALLOONTIP :: struct {
PEDITBALLOONTIP :: ^EDITBALLOONTIP
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 {
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 {
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))
}
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 {
return cast(c_int)SendMessageW(hwndLV, LVM_HITTEST, 0, cast(LPARAM)uintptr(pinfo))
+3 -3
View File
@@ -38,9 +38,9 @@ IP_Adapter_Addresses :: struct {
FirstAnycastAddress: ^IP_ADAPTER_ANYCAST_ADDRESS_XP,
FirstMulticastAddress: ^IP_ADAPTER_MULTICAST_ADDRESS_XP,
FirstDnsServerAddress: ^IP_ADAPTER_DNS_SERVER_ADDRESS_XP,
DnsSuffix: ^u16,
Description: ^u16,
FriendlyName: ^u16,
DnsSuffix: cstring16,
Description: cstring16,
FriendlyName: cstring16,
PhysicalAddress: [8]u8,
PhysicalAddressLength: u32,
Anonymous2: struct #raw_union {
+1 -1
View File
@@ -258,7 +258,7 @@ foreign kernel32 {
) -> BOOL ---
CreateProcessW :: proc(
lpApplicationName: LPCWSTR,
lpCommandLine: LPWSTR,
lpCommandLine: LPCWSTR,
lpProcessAttributes: LPSECURITY_ATTRIBUTES,
lpThreadAttributes: LPSECURITY_ATTRIBUTES,
bInheritHandles: BOOL,
+1 -1
View File
@@ -58,7 +58,7 @@ foreign Ole32 {
CoTaskMemFree :: proc(pv: rawptr) ---
CLSIDFromProgID :: proc(lpszProgID: LPCOLESTR, lpclsid: LPCLSID) -> HRESULT ---
CLSIDFromProgIDEx :: proc(lpszProgID, LPCOLESTR, lpclsid: LPCLSID) -> HRESULT ---
CLSIDFromProgIDEx :: proc(lpszProgID: LPCOLESTR, lpclsid: LPCLSID) -> HRESULT ---
CLSIDFromString :: proc(lpsz: LPOLESTR, pclsid: LPCLSID) -> HRESULT ---
IIDFromString :: proc(lpsz: LPOLESTR, lpiid: LPIID) -> HRESULT ---
ProgIDFromCLSID :: proc(clsid: REFCLSID, lplpszProgID: ^LPOLESTR) -> HRESULT ---
+17 -4
View File
@@ -107,8 +107,8 @@ PDWORD64 :: ^DWORD64
PDWORD_PTR :: ^DWORD_PTR
ATOM :: distinct WORD
wstring :: [^]WCHAR
PWSTR :: [^]WCHAR
wstring :: cstring16
PWSTR :: cstring16
PBYTE :: ^BYTE
LPBYTE :: ^BYTE
@@ -145,7 +145,7 @@ LPSTR :: ^CHAR
LPWSTR :: ^WCHAR
OLECHAR :: WCHAR
BSTR :: ^OLECHAR
LPOLESTR :: ^OLECHAR
LPOLESTR :: cstring16
LPCOLESTR :: LPCSTR
LPFILETIME :: ^FILETIME
LPWSABUF :: ^WSABUF
@@ -1698,7 +1698,7 @@ NM_FONTCHANGED :: NM_OUTOFMEMORY-22
NM_CUSTOMTEXT :: NM_OUTOFMEMORY-23 // uses NMCUSTOMTEXT struct
NM_TVSTATEIMAGECHANGING :: NM_OUTOFMEMORY-23 // uses NMTVSTATEIMAGECHANGING struct, defined after HTREEITEM
PCZZWSTR :: ^WCHAR
PCZZWSTR :: cstring16
SHFILEOPSTRUCTW :: struct {
hwnd: HWND,
@@ -3385,6 +3385,19 @@ FILE_ATTRIBUTE_TAG_INFO :: struct {
ReparseTag: DWORD,
}
// getaddrinfo flags https://learn.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-addrinfoa
AI_PASSIVE :: 0x01
AI_CANONNAME :: 0x02
AI_NUMERICHOST :: 0x04
AI_ALL :: 0x0100
AI_ADDRCONFIG :: 0x0400
AI_V4MAPPED :: 0x0800
AI_NON_AUTHORITATIVE :: 0x04000
AI_SECURE :: 0x08000
AI_RETURN_PREFERRED_NAMES :: 0x010000
AI_FQDN :: 0x00020000
AI_FILESERVER :: 0x00040000
PADDRINFOEXW :: ^ADDRINFOEXW
LPADDRINFOEXW :: ^ADDRINFOEXW
ADDRINFOEXW :: struct {
+27 -27
View File
@@ -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 {
if res := utf8_to_utf16(s, allocator); len(res) > 0 {
return raw_data(res)
return wstring(raw_data(res))
}
return nil
}
utf8_to_wstring_buf :: proc(buf: []u16, s: string) -> wstring {
if res := utf8_to_utf16(buf, s); len(res) > 0 {
return raw_data(res)
return wstring(raw_data(res))
}
return nil
}
@@ -215,7 +215,7 @@ utf16_to_utf8_alloc :: proc(s: []u16, allocator := context.temp_allocator) -> (r
if len(s) == 0 {
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 {
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}
@@ -298,7 +298,7 @@ _add_user :: proc(servername: string, username: string, password: string) -> (ok
servername_w = nil
} else {
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 {
@@ -348,7 +348,7 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s
res := LookupAccountNameW(
nil, // Look on this computer first
&username_w[0],
wstring(&username_w[0]),
&sid,
&cbsid,
nil,
@@ -364,10 +364,10 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s
res = LookupAccountNameW(
nil,
&username_w[0],
wstring(&username_w[0]),
&sid,
&cbsid,
&cname_w[0],
wstring(&cname_w[0]),
&computer_name_size,
&pe_use,
)
@@ -390,7 +390,7 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) {
res := LookupAccountNameW(
nil, // Look on this computer first
&username_w[0],
wstring(&username_w[0]),
sid,
&cbsid,
nil,
@@ -406,10 +406,10 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) {
res = LookupAccountNameW(
nil,
&username_w[0],
wstring(&username_w[0]),
sid,
&cbsid,
&cname_w[0],
wstring(&cname_w[0]),
&computer_name_size,
&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)
ok = NetLocalGroupAddMembers(
nil,
&group_name[0],
wstring(&group_name[0]),
0,
&group_member,
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)
ok = NetLocalGroupDelMembers(
nil,
&group_name[0],
cstring16(&group_name[0]),
0,
&group_member,
1,
@@ -465,19 +465,19 @@ add_user_profile :: proc(username: string) -> (ok: bool, profile_path: string) {
if res == false {
return false, ""
}
defer LocalFree(sb)
defer LocalFree(rawptr(sb))
pszProfilePath := make([]u16, 257, context.temp_allocator)
res2 := CreateProfile(
sb,
&username_w[0],
&pszProfilePath[0],
cstring16(&username_w[0]),
cstring16(&pszProfilePath[0]),
257,
)
if res2 != 0 {
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
}
@@ -495,7 +495,7 @@ delete_user_profile :: proc(username: string) -> (ok: bool) {
if res == false {
return false
}
defer LocalFree(sb)
defer LocalFree(rawptr(sb))
res2 := DeleteProfileW(
sb,
@@ -548,13 +548,13 @@ delete_user :: proc(servername: string, username: string) -> (ok: bool) {
servername_w = nil
} else {
server := utf8_to_utf16(servername, context.temp_allocator)
servername_w = &server[0]
servername_w = wstring(&server[0])
}
username_w := utf8_to_utf16(username)
res := NetUserDel(
servername_w,
&username_w[0],
wstring(&username_w[0]),
)
if res != .Success {
return false
@@ -586,9 +586,9 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P
user_token: HANDLE
ok = bool(LogonUserW(
lpszUsername = &username_w[0],
lpszDomain = &domain_w[0],
lpszPassword = &password_w[0],
lpszUsername = wstring(&username_w[0]),
lpszDomain = wstring(&domain_w[0]),
lpszPassword = wstring(&password_w[0]),
dwLogonType = .NEW_CREDENTIALS,
dwLogonProvider = .WINNT50,
phToken = &user_token,
@@ -605,8 +605,8 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P
ok = bool(CreateProcessAsUserW(
user_token,
&app_w[0],
&commandline_w[0],
wstring(&app_w[0]),
wstring(&commandline_w[0]),
nil, // lpProcessAttributes,
nil, // lpThreadAttributes,
false, // bInheritHandles,
@@ -628,7 +628,7 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P
}
}
ensure_winsock_initialized :: proc() {
ensure_winsock_initialized :: proc "contextless" () {
@static gate := false
@static initted := false
@@ -644,7 +644,7 @@ ensure_winsock_initialized :: proc() {
unused_info: WSADATA
version_requested := WORD(2) << 8 | 2
res := WSAStartup(version_requested, &unused_info)
assert(res == 0, "unable to initialized Winsock2")
assert_contextless(res == 0, "unable to initialized Winsock2")
initted = true
}
+2 -1
View File
@@ -82,7 +82,8 @@ foreign Opengl32 {
wglSetLayerPaletteEntries :: proc(hdc: HDC, layer_plane, start, entries: c.int, cr: ^COLORREF) -> c.int ---
wglShareLists :: proc(HGLRC1, HGLRC2: HGLRC) -> BOOL ---
wglSwapLayerBuffers :: proc(hdc: HDC, planes: DWORD) -> BOOL ---
wglUseFontBitmaps :: proc(hdc: HDC, first, count, list_base: DWORD) -> BOOL ---
wglUseFontBitmapsA :: proc(hdc: HDC, first, count, list_base: DWORD) -> BOOL ---
wglUseFontBitmapsW :: proc(hdc: HDC, first, count, list_base: DWORD) -> BOOL ---
wglUseFontOutlines :: proc(hdc: HDC, first, count, list_base: DWORD, deviation, extrusion: f32, format: c.int, gmf: LPGLYPHMETRICSFLOAT) -> BOOL ---
}
+12 -1
View File
@@ -82,6 +82,17 @@ Example Load:
}
*/
LPFN_GETACCEPTEXSOCKADDRS :: #type proc "system" (
lpOutputBuffer: PVOID,
dwReceiveDataLength: DWORD,
dwLocalAddressLength: DWORD,
dwRemoteAddressLength: DWORD,
LocalSockaddr: ^^sockaddr,
LocalSockaddrLength: LPINT,
RemoteSockaddr: ^^sockaddr,
RemoteSockaddrLength: LPINT,
)
foreign import ws2_32 "system:Ws2_32.lib"
@(default_calling_convention="system")
foreign ws2_32 {
@@ -248,4 +259,4 @@ foreign ws2_32 {
// [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htons)
// Prefer using endian-specific integers instead, https://odin-lang.org/docs/overview/#basic-types
htons :: proc(hostshort: c_ushort) -> c_ushort ---
}
}
+5 -2
View File
@@ -1,6 +1,7 @@
#+private
package terminal
import "base:runtime"
import "core:os"
import "core:strings"
@@ -68,9 +69,11 @@ get_environment_color :: proc() -> Color_Depth {
}
@(init)
init_terminal :: proc() {
init_terminal :: proc "contextless" () {
_init_terminal()
context = runtime.default_context()
// We respect `NO_COLOR` specifically as a color-disabler but not as a
// blanket ban on any terminal manipulation codes, hence why this comes
// after `_init_terminal` which will allow Windows to enable Virtual
@@ -81,6 +84,6 @@ init_terminal :: proc() {
}
@(fini)
fini_terminal :: proc() {
fini_terminal :: proc "contextless" () {
_fini_terminal()
}
+3 -3
View File
@@ -4,12 +4,12 @@ package terminal
import "core:os"
_is_terminal :: proc(handle: os.Handle) -> bool {
_is_terminal :: proc "contextless" (handle: os.Handle) -> bool {
return true
}
_init_terminal :: proc() {
_init_terminal :: proc "contextless" () {
color_depth = .None
}
_fini_terminal :: proc() { }
_fini_terminal :: proc "contextless" () { }
+5 -3
View File
@@ -2,15 +2,17 @@
#+build linux, darwin, netbsd, openbsd, freebsd, haiku
package terminal
import "base:runtime"
import "core:os"
import "core:sys/posix"
_is_terminal :: proc(handle: os.Handle) -> bool {
_is_terminal :: proc "contextless" (handle: os.Handle) -> bool {
return bool(posix.isatty(posix.FD(handle)))
}
_init_terminal :: proc() {
_init_terminal :: proc "contextless" () {
context = runtime.default_context()
color_depth = get_environment_color()
}
_fini_terminal :: proc() { }
_fini_terminal :: proc "contextless" () { }
+6 -3
View File
@@ -1,10 +1,11 @@
#+private
package terminal
import "base:runtime"
import "core:os"
import "core:sys/windows"
_is_terminal :: proc(handle: os.Handle) -> bool {
_is_terminal :: proc "contextless" (handle: os.Handle) -> bool {
is_tty := windows.GetFileType(windows.HANDLE(handle)) == windows.FILE_TYPE_CHAR
return is_tty
}
@@ -18,7 +19,7 @@ old_modes: [2]struct{
}
@(init)
_init_terminal :: proc() {
_init_terminal :: proc "contextless" () {
vtp_enabled: bool
for &v in old_modes {
@@ -42,13 +43,15 @@ _init_terminal :: proc() {
// This color depth is available on Windows 10 since build 10586.
color_depth = .Four_Bit
} else {
context = runtime.default_context()
// The user may be on a non-default terminal emulator.
color_depth = get_environment_color()
}
}
@(fini)
_fini_terminal :: proc() {
_fini_terminal :: proc "contextless" () {
for v in old_modes {
handle := windows.GetStdHandle(v.handle)
if handle == windows.INVALID_HANDLE || handle == nil {
+4 -4
View File
@@ -159,9 +159,9 @@ iana_to_windows_tz :: proc(iana_name: string, allocator := context.allocator) ->
status: windows.UError
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 {
return
}
@@ -178,7 +178,7 @@ local_tz_name :: proc(allocator := context.allocator) -> (name: string, success:
iana_name_buffer: [128]u16
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 {
return
}
@@ -291,7 +291,7 @@ _region_load :: proc(reg_str: string, allocator := context.allocator) -> (out_re
defer delete(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
res := windows.RegOpenKeyExW(windows.HKEY_LOCAL_MACHINE, tz_key_wstr, 0, windows.KEY_READ, &key)
+51 -1
View File
@@ -106,7 +106,57 @@ decode :: proc(d: []rune, s: []u16) -> (n: int) {
return
}
rune_count :: proc(s: []u16) -> (n: int) {
decode_rune_in_string :: proc(s: string16) -> (r: rune, width: int) {
r = rune(REPLACEMENT_CHAR)
n := len(s)
if n < 1 {
return
}
width = 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:
r = decode_surrogate_pair(rune(c), rune(s[1]))
width += 1
}
return
}
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 {
c := s[i]
if _surr1 <= c && c < _surr2 && i+1 < len(s) &&