From 304f22c8af635124357c5f62772f6f09676aa761 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Tue, 28 Oct 2025 00:16:42 +0100 Subject: `core:os` -> `core:os/os` for CSV, INI, and XML Also had to vendor `core:encoding/ini` into `core:os/os2` for the user directories on *nix, as it used that package to read `~/.config/user-dirs.dirs`, causing an import cycle. --- core/encoding/xml/xml_reader.odin | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'core/encoding/xml/xml_reader.odin') diff --git a/core/encoding/xml/xml_reader.odin b/core/encoding/xml/xml_reader.odin index 8f8fffe14..798eb3f87 100644 --- a/core/encoding/xml/xml_reader.odin +++ b/core/encoding/xml/xml_reader.odin @@ -9,13 +9,13 @@ package encoding_xml - Jeroen van Rijn: Initial implementation. */ -import "core:bytes" -import "core:encoding/entity" -import "base:intrinsics" -import "core:mem" -import "core:os" -import "core:strings" -import "base:runtime" +import "base:runtime" +import "core:bytes" +import "core:encoding/entity" +import "base:intrinsics" +import "core:mem" +import os "core:os/os2" +import "core:strings" likely :: intrinsics.expect @@ -378,8 +378,8 @@ load_from_file :: proc(filename: string, options := DEFAULT_OPTIONS, error_handl context.allocator = allocator options := options - data, data_ok := os.read_entire_file(filename) - if !data_ok { return {}, .File_Error } + data, data_err := os.read_entire_file(filename, allocator) + if data_err != nil { return {}, .File_Error } options.flags += { .Input_May_Be_Modified } -- cgit v1.2.3 From 8ed264680b1f3f94b6aa5176824d4ccadfc30322 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 8 Feb 2026 16:39:56 +0100 Subject: Remove all `core:os` imports from JS targets Fix `local_tz_name` on FreeBSD. --- core/crypto/hash/hash_js.odin | 10 +++++ core/crypto/hash/hash_os.odin | 1 + core/encoding/hxa/hxa_os.odin | 34 +++++++++++++++ core/encoding/hxa/read.odin | 15 ------- core/encoding/hxa/write.odin | 16 ------- core/encoding/ini/ini.odin | 15 ------- core/encoding/ini/ini_os.odin | 20 +++++++++ core/encoding/xml/xml_os.odin | 18 ++++++++ core/encoding/xml/xml_reader.odin | 14 ------ core/log/file_console_logger.odin | 1 + core/math/big/radix.odin | 57 ------------------------ core/math/big/radix_os.odin | 79 +++++++++++++++++++++++++++++++++ core/mem/virtual/common.odin | 16 +++++++ core/mem/virtual/file.odin | 17 +------- core/terminal/internal.odin | 80 ---------------------------------- core/terminal/internal_os.odin | 82 +++++++++++++++++++++++++++++++++++ core/terminal/terminal.odin | 4 +- core/text/i18n/gettext.odin | 8 ---- core/text/i18n/i18_js.odin | 18 ++++++++ core/text/i18n/i18n.odin | 11 ----- core/text/i18n/i18n_os.odin | 38 ++++++++++++++++ core/text/i18n/qt_linguist.odin | 6 --- core/text/regex/common/common.odin | 2 + core/text/regex/common/debugging.odin | 7 --- core/text/regex/common/os.odin | 17 ++++++++ core/text/table/utility.odin | 2 + core/time/timezone/tz_os.odin | 19 ++++++++ core/time/timezone/tz_unix.odin | 2 +- core/time/timezone/tzdate.odin | 4 -- core/time/timezone/tzif.odin | 11 ----- examples/all/all_js.odin | 7 +-- tests/core/time/test_core_time.odin | 4 +- 32 files changed, 368 insertions(+), 267 deletions(-) create mode 100644 core/crypto/hash/hash_js.odin create mode 100644 core/encoding/hxa/hxa_os.odin create mode 100644 core/encoding/ini/ini_os.odin create mode 100644 core/encoding/xml/xml_os.odin create mode 100644 core/math/big/radix_os.odin create mode 100644 core/mem/virtual/common.odin delete mode 100644 core/terminal/internal.odin create mode 100644 core/terminal/internal_os.odin create mode 100644 core/text/i18n/i18_js.odin create mode 100644 core/text/i18n/i18n_os.odin create mode 100644 core/text/regex/common/os.odin create mode 100644 core/time/timezone/tz_os.odin (limited to 'core/encoding/xml/xml_reader.odin') diff --git a/core/crypto/hash/hash_js.odin b/core/crypto/hash/hash_js.odin new file mode 100644 index 000000000..99309b944 --- /dev/null +++ b/core/crypto/hash/hash_js.odin @@ -0,0 +1,10 @@ +#+build js +package crypto_hash + +hash :: proc { + hash_stream, + hash_bytes, + hash_string, + hash_bytes_to_buffer, + hash_string_to_buffer, +} diff --git a/core/crypto/hash/hash_os.odin b/core/crypto/hash/hash_os.odin index 28db9c61f..5155623cb 100644 --- a/core/crypto/hash/hash_os.odin +++ b/core/crypto/hash/hash_os.odin @@ -1,4 +1,5 @@ #+build !freestanding +#+build !js package crypto_hash import "core:io" diff --git a/core/encoding/hxa/hxa_os.odin b/core/encoding/hxa/hxa_os.odin new file mode 100644 index 000000000..c033bdca8 --- /dev/null +++ b/core/encoding/hxa/hxa_os.odin @@ -0,0 +1,34 @@ +#+build !freestanding +#+build !js +package encoding_hxa + +import os "core:os/os2" + +read_from_file :: proc(filename: string, print_error := false, allocator := context.allocator, loc := #caller_location) -> (file: File, err: Read_Error) { + context.allocator = allocator + + data, data_err := os.read_entire_file(filename, allocator, loc) + if data_err != nil { + err = .Unable_To_Read_File + delete(data, allocator) + return + } + file, err = read(data, filename, print_error, allocator) + file.backing = data + return +} + +write_to_file :: proc(filepath: string, file: File) -> (err: Write_Error) { + required := required_write_size(file) + buf, alloc_err := make([]byte, required) + if alloc_err == .Out_Of_Memory { + return .Failed_File_Write + } + defer delete(buf) + + write_internal(&Writer{data = buf}, file) + if os.write_entire_file(filepath, buf) != nil { + err =.Failed_File_Write + } + return +} diff --git a/core/encoding/hxa/read.odin b/core/encoding/hxa/read.odin index 1f1c3633e..1721bf7fc 100644 --- a/core/encoding/hxa/read.odin +++ b/core/encoding/hxa/read.odin @@ -1,7 +1,6 @@ package encoding_hxa import "core:fmt" -import os "core:os/os2" import "core:mem" Read_Error :: enum { @@ -11,20 +10,6 @@ Read_Error :: enum { Unable_To_Read_File, } -read_from_file :: proc(filename: string, print_error := false, allocator := context.allocator, loc := #caller_location) -> (file: File, err: Read_Error) { - context.allocator = allocator - - data, data_err := os.read_entire_file(filename, allocator, loc) - if data_err != nil { - err = .Unable_To_Read_File - delete(data, allocator) - return - } - file, err = read(data, filename, print_error, allocator) - file.backing = data - return -} - read :: proc(data: []byte, filename := "", print_error := false, allocator := context.allocator, loc := #caller_location) -> (file: File, err: Read_Error) { Reader :: struct { filename: string, diff --git a/core/encoding/hxa/write.odin b/core/encoding/hxa/write.odin index e8ef9a139..cbf9c7cb6 100644 --- a/core/encoding/hxa/write.odin +++ b/core/encoding/hxa/write.odin @@ -1,6 +1,5 @@ package encoding_hxa -import os "core:os/os2" import "core:mem" Write_Error :: enum { @@ -9,21 +8,6 @@ Write_Error :: enum { Failed_File_Write, } -write_to_file :: proc(filepath: string, file: File) -> (err: Write_Error) { - required := required_write_size(file) - buf, alloc_err := make([]byte, required) - if alloc_err == .Out_Of_Memory { - return .Failed_File_Write - } - defer delete(buf) - - write_internal(&Writer{data = buf}, file) - if os.write_entire_file(filepath, buf) != nil { - err =.Failed_File_Write - } - return -} - write :: proc(buf: []byte, file: File) -> (n: int, err: Write_Error) { required := required_write_size(file) if len(buf) < required { diff --git a/core/encoding/ini/ini.odin b/core/encoding/ini/ini.odin index 644ce8937..8bf6c6c9a 100644 --- a/core/encoding/ini/ini.odin +++ b/core/encoding/ini/ini.odin @@ -6,7 +6,6 @@ import "base:intrinsics" import "core:strings" import "core:strconv" import "core:io" -import os "core:os/os2" import "core:fmt" _ :: fmt @@ -120,20 +119,6 @@ load_map_from_string :: proc(src: string, allocator: runtime.Allocator, options return } -load_map_from_path :: proc(path: string, allocator: runtime.Allocator, options := DEFAULT_OPTIONS) -> (m: Map, err: runtime.Allocator_Error, ok: bool) { - data, data_err := os.read_entire_file(path, allocator) - defer delete(data, allocator) - if data_err != nil { - return - } - m, err = load_map_from_string(string(data), allocator, options) - ok = err == nil - defer if !ok { - delete_map(m) - } - return -} - save_map_to_string :: proc(m: Map, allocator: runtime.Allocator) -> (data: string) { b := strings.builder_make(allocator) _, _ = write_map(strings.to_writer(&b), m) diff --git a/core/encoding/ini/ini_os.odin b/core/encoding/ini/ini_os.odin new file mode 100644 index 000000000..619a0e2a6 --- /dev/null +++ b/core/encoding/ini/ini_os.odin @@ -0,0 +1,20 @@ +#+build !freestanding +#+build !js +package encoding_ini + +import "base:runtime" +import os "core:os/os2" + +load_map_from_path :: proc(path: string, allocator: runtime.Allocator, options := DEFAULT_OPTIONS) -> (m: Map, err: runtime.Allocator_Error, ok: bool) { + data, data_err := os.read_entire_file(path, allocator) + defer delete(data, allocator) + if data_err != nil { + return + } + m, err = load_map_from_string(string(data), allocator, options) + ok = err == nil + defer if !ok { + delete_map(m) + } + return +} diff --git a/core/encoding/xml/xml_os.odin b/core/encoding/xml/xml_os.odin new file mode 100644 index 000000000..8c7f6cccf --- /dev/null +++ b/core/encoding/xml/xml_os.odin @@ -0,0 +1,18 @@ +#+build !freestanding +#+build !js +package encoding_xml + +import os "core:os/os2" + +// Load an XML file +load_from_file :: proc(filename: string, options := DEFAULT_OPTIONS, error_handler := default_error_handler, allocator := context.allocator) -> (doc: ^Document, err: Error) { + context.allocator = allocator + options := options + + data, data_err := os.read_entire_file(filename, allocator) + if data_err != nil { return {}, .File_Error } + + options.flags += { .Input_May_Be_Modified } + + return parse_bytes(data, options, filename, error_handler, allocator) +} diff --git a/core/encoding/xml/xml_reader.odin b/core/encoding/xml/xml_reader.odin index 798eb3f87..6d068466b 100644 --- a/core/encoding/xml/xml_reader.odin +++ b/core/encoding/xml/xml_reader.odin @@ -14,7 +14,6 @@ import "core:bytes" import "core:encoding/entity" import "base:intrinsics" import "core:mem" -import os "core:os/os2" import "core:strings" likely :: intrinsics.expect @@ -373,19 +372,6 @@ parse_string :: proc(data: string, options := DEFAULT_OPTIONS, path := "", error parse :: proc { parse_string, parse_bytes } -// Load an XML file -load_from_file :: proc(filename: string, options := DEFAULT_OPTIONS, error_handler := default_error_handler, allocator := context.allocator) -> (doc: ^Document, err: Error) { - context.allocator = allocator - options := options - - data, data_err := os.read_entire_file(filename, allocator) - if data_err != nil { return {}, .File_Error } - - options.flags += { .Input_May_Be_Modified } - - return parse_bytes(data, options, filename, error_handler, allocator) -} - destroy :: proc(doc: ^Document, allocator := context.allocator) { context.allocator = allocator if doc == nil { return } diff --git a/core/log/file_console_logger.odin b/core/log/file_console_logger.odin index a9b073c18..819d494e9 100644 --- a/core/log/file_console_logger.odin +++ b/core/log/file_console_logger.odin @@ -1,5 +1,6 @@ #+build !freestanding #+build !orca +#+build !js package log import "base:runtime" diff --git a/core/math/big/radix.odin b/core/math/big/radix.odin index c0ea8cb79..0d57bc071 100644 --- a/core/math/big/radix.odin +++ b/core/math/big/radix.odin @@ -17,7 +17,6 @@ package math_big import "base:intrinsics" import "core:mem" -import os "core:os/os2" /* This version of `itoa` allocates on behalf of the caller. The caller must free the string. @@ -386,63 +385,7 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con return size, nil } -/* - We might add functions to read and write byte-encoded Ints from/to files, using `int_to_bytes_*` functions. - - LibTomMath allows exporting/importing to/from a file in ASCII, but it doesn't support a much more compact representation in binary, even though it has several pack functions int_to_bytes_* (which I expanded upon and wrote Python interoperable versions of as well), and (un)pack, which is GMP compatible. - Someone could implement their own read/write binary int procedures, of course. - - Could be worthwhile to add a canonical binary file representation with an optional small header that says it's an Odin big.Int, big.Rat or Big.Float, byte count for each component that follows, flag for big/little endian and a flag that says a checksum exists at the end of the file. - For big.Rat and big.Float the header couldn't be optional, because we'd have no way to distinguish where the components end. -*/ - -/* - Read an Int from an ASCII file. -*/ -internal_int_read_from_ascii_file :: proc(a: ^Int, filename: string, radix := i8(10), allocator := context.allocator) -> (err: Error) { - context.allocator = allocator - - /* - We can either read the entire file at once, or read a bunch at a time and keep multiplying by the radix. - For now, we'll read the entire file. Eventually we'll replace this with a copy that duplicates the logic - of `atoi` so we don't need to read the entire file. - */ - res, res_err := os.read_entire_file(filename, allocator) - defer delete(res, allocator) - if res_err != nil { - return .Cannot_Read_File - } - - as := string(res) - return atoi(a, as, radix) -} - -/* - Write an Int to an ASCII file. -*/ -internal_int_write_to_ascii_file :: proc(a: ^Int, filename: string, radix := i8(10), allocator := context.allocator) -> (err: Error) { - context.allocator = allocator - - /* - For now we'll convert the Int using itoa and writing the result in one go. - If we want to preserve memory we could duplicate the itoa logic and write backwards. - */ - - as := itoa(a, radix) or_return - defer delete(as) - - l := len(as) - assert(l > 0) - - data := transmute([]u8)mem.Raw_Slice{ - data = raw_data(as), - len = l, - } - - write_err := os.write_entire_file(filename, data, truncate=true) - return nil if write_err == nil else .Cannot_Write_File -} /* Calculate the size needed for `internal_int_pack`. diff --git a/core/math/big/radix_os.odin b/core/math/big/radix_os.odin new file mode 100644 index 000000000..8269a4338 --- /dev/null +++ b/core/math/big/radix_os.odin @@ -0,0 +1,79 @@ +#+build !freestanding +#+build !js +package math_big + +/* + Copyright 2021 Jeroen van Rijn . + Made available under Odin's license. + + An arbitrary precision mathematics implementation in Odin. + For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. + The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks. + + This file contains radix conversions, `string_to_int` (atoi) and `int_to_string` (itoa). + + TODO: + - Use Barrett reduction for non-powers-of-two. + - Also look at extracting and splatting several digits at once. +*/ + +import "core:mem" +import os "core:os/os2" + +/* + We might add functions to read and write byte-encoded Ints from/to files, using `int_to_bytes_*` functions. + + LibTomMath allows exporting/importing to/from a file in ASCII, but it doesn't support a much more compact representation in binary, even though it has several pack functions int_to_bytes_* (which I expanded upon and wrote Python interoperable versions of as well), and (un)pack, which is GMP compatible. + Someone could implement their own read/write binary int procedures, of course. + + Could be worthwhile to add a canonical binary file representation with an optional small header that says it's an Odin big.Int, big.Rat or Big.Float, byte count for each component that follows, flag for big/little endian and a flag that says a checksum exists at the end of the file. + For big.Rat and big.Float the header couldn't be optional, because we'd have no way to distinguish where the components end. +*/ + +/* + Read an Int from an ASCII file. +*/ +internal_int_read_from_ascii_file :: proc(a: ^Int, filename: string, radix := i8(10), allocator := context.allocator) -> (err: Error) { + context.allocator = allocator + + /* + We can either read the entire file at once, or read a bunch at a time and keep multiplying by the radix. + For now, we'll read the entire file. Eventually we'll replace this with a copy that duplicates the logic + of `atoi` so we don't need to read the entire file. + */ + res, res_err := os.read_entire_file(filename, allocator) + defer delete(res, allocator) + + if res_err != nil { + return .Cannot_Read_File + } + + as := string(res) + return atoi(a, as, radix) +} + +/* + Write an Int to an ASCII file. +*/ +internal_int_write_to_ascii_file :: proc(a: ^Int, filename: string, radix := i8(10), allocator := context.allocator) -> (err: Error) { + context.allocator = allocator + + /* + For now we'll convert the Int using itoa and writing the result in one go. + If we want to preserve memory we could duplicate the itoa logic and write backwards. + */ + + as := itoa(a, radix) or_return + defer delete(as) + + l := len(as) + assert(l > 0) + + data := transmute([]u8)mem.Raw_Slice{ + data = raw_data(as), + len = l, + } + + write_err := os.write_entire_file(filename, data, truncate=true) + return nil if write_err == nil else .Cannot_Write_File +} \ No newline at end of file diff --git a/core/mem/virtual/common.odin b/core/mem/virtual/common.odin new file mode 100644 index 000000000..ad8505c89 --- /dev/null +++ b/core/mem/virtual/common.odin @@ -0,0 +1,16 @@ +package mem_virtual + +Map_File_Error :: enum { + None, + Open_Failure, + Stat_Failure, + Negative_Size, + Too_Large_Size, + Map_Failure, +} + +Map_File_Flag :: enum u32 { + Read, + Write, +} +Map_File_Flags :: distinct bit_set[Map_File_Flag; u32] \ No newline at end of file diff --git a/core/mem/virtual/file.odin b/core/mem/virtual/file.odin index c532335c5..b156f2af4 100644 --- a/core/mem/virtual/file.odin +++ b/core/mem/virtual/file.odin @@ -1,22 +1,9 @@ +#+build !freestanding +#+build !js package mem_virtual import os "core:os/os2" -Map_File_Error :: enum { - None, - Open_Failure, - Stat_Failure, - Negative_Size, - Too_Large_Size, - Map_Failure, -} - -Map_File_Flag :: enum u32 { - Read, - Write, -} -Map_File_Flags :: distinct bit_set[Map_File_Flag; u32] - map_file :: proc{ map_file_from_path, map_file_from_file, diff --git a/core/terminal/internal.odin b/core/terminal/internal.odin deleted file mode 100644 index 956726b8a..000000000 --- a/core/terminal/internal.odin +++ /dev/null @@ -1,80 +0,0 @@ -#+private -package terminal - -import "base:runtime" -import os "core:os/os2" -import "core:strings" - -// Reference documentation: -// -// - [[ https://no-color.org/ ]] -// - [[ https://github.com/termstandard/colors ]] -// - [[ https://invisible-island.net/ncurses/terminfo.src.html ]] - -get_no_color :: proc() -> bool { - buf: [128]u8 - if no_color, err := os.lookup_env(buf[:], "NO_COLOR"); err == nil { - return no_color != "" - } - return false -} - -get_environment_color :: proc() -> Color_Depth { - buf: [128]u8 - // `COLORTERM` is non-standard but widespread and unambiguous. - if colorterm, err := os.lookup_env(buf[:], "COLORTERM"); err == nil { - // These are the only values that are typically advertised that have - // anything to do with color depth. - if colorterm == "truecolor" || colorterm == "24bit" { - return .True_Color - } - } - - if term, err := os.lookup_env(buf[:], "TERM"); err == nil { - if strings.contains(term, "-truecolor") { - return .True_Color - } - if strings.contains(term, "-256color") { - return .Eight_Bit - } - if strings.contains(term, "-16color") { - return .Four_Bit - } - - // The `terminfo` database, which is stored in binary on *nix - // platforms, has an undocumented format that is not guaranteed to be - // portable, so beyond this point, we can only make safe assumptions. - // - // This section should only be necessary for terminals that do not - // define any of the previous environment values. - // - // Only a small sampling of some common values are checked here. - switch term { - case "ansi", "konsole", "putty", "rxvt", "rxvt-color", "screen", - "st", "tmux", "vte", "xterm", "xterm-color": - return .Three_Bit - } - } - - return .None -} - -@(init) -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 - // Terminal Processing for non-color control sequences. - if !get_no_color() { - color_enabled = color_depth > .None - } -} - -@(fini) -fini_terminal :: proc "contextless" () { - _fini_terminal() -} \ No newline at end of file diff --git a/core/terminal/internal_os.odin b/core/terminal/internal_os.odin new file mode 100644 index 000000000..841803766 --- /dev/null +++ b/core/terminal/internal_os.odin @@ -0,0 +1,82 @@ +#+build !freestanding +#+build !js +#+private +package terminal + +import "base:runtime" +import os "core:os/os2" +import "core:strings" + +// Reference documentation: +// +// - [[ https://no-color.org/ ]] +// - [[ https://github.com/termstandard/colors ]] +// - [[ https://invisible-island.net/ncurses/terminfo.src.html ]] + +get_no_color :: proc() -> bool { + buf: [128]u8 + if no_color, err := os.lookup_env(buf[:], "NO_COLOR"); err == nil { + return no_color != "" + } + return false +} + +get_environment_color :: proc() -> Color_Depth { + buf: [128]u8 + // `COLORTERM` is non-standard but widespread and unambiguous. + if colorterm, err := os.lookup_env(buf[:], "COLORTERM"); err == nil { + // These are the only values that are typically advertised that have + // anything to do with color depth. + if colorterm == "truecolor" || colorterm == "24bit" { + return .True_Color + } + } + + if term, err := os.lookup_env(buf[:], "TERM"); err == nil { + if strings.contains(term, "-truecolor") { + return .True_Color + } + if strings.contains(term, "-256color") { + return .Eight_Bit + } + if strings.contains(term, "-16color") { + return .Four_Bit + } + + // The `terminfo` database, which is stored in binary on *nix + // platforms, has an undocumented format that is not guaranteed to be + // portable, so beyond this point, we can only make safe assumptions. + // + // This section should only be necessary for terminals that do not + // define any of the previous environment values. + // + // Only a small sampling of some common values are checked here. + switch term { + case "ansi", "konsole", "putty", "rxvt", "rxvt-color", "screen", + "st", "tmux", "vte", "xterm", "xterm-color": + return .Three_Bit + } + } + + return .None +} + +@(init) +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 + // Terminal Processing for non-color control sequences. + if !get_no_color() { + color_enabled = color_depth > .None + } +} + +@(fini) +fini_terminal :: proc "contextless" () { + _fini_terminal() +} \ No newline at end of file diff --git a/core/terminal/terminal.odin b/core/terminal/terminal.odin index d24b963d3..86d928649 100644 --- a/core/terminal/terminal.odin +++ b/core/terminal/terminal.odin @@ -1,8 +1,6 @@ // Interaction with the command line interface (`CLI`) of the system. package terminal -import os "core:os/os2" - /* This describes the range of colors that a terminal is capable of supporting. */ @@ -21,7 +19,7 @@ This is normally true for `os.stdout` and `os.stderr` unless they are redirected to a file. */ @(require_results) -is_terminal :: proc(f: ^os.File) -> bool { +is_terminal :: proc(f: $T) -> bool { return _is_terminal(f) } diff --git a/core/text/i18n/gettext.odin b/core/text/i18n/gettext.odin index 4aa86a35d..b0e3dae67 100644 --- a/core/text/i18n/gettext.odin +++ b/core/text/i18n/gettext.odin @@ -125,14 +125,6 @@ parse_mo_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTIONS, plur return } -parse_mo_file :: proc(filename: string, options := DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) { - data := read_file(filename, allocator) or_return - defer delete(data) - return parse_mo_from_bytes(data, options, pluralizer, allocator) -} - -parse_mo :: proc { parse_mo_file, parse_mo_from_bytes } - @(private) read_u32 :: proc(data: []u8, native_endian := true) -> (res: u32, err: Error) { if len(data) < size_of(u32) { return 0, .Premature_EOF } diff --git a/core/text/i18n/i18_js.odin b/core/text/i18n/i18_js.odin new file mode 100644 index 000000000..743718942 --- /dev/null +++ b/core/text/i18n/i18_js.odin @@ -0,0 +1,18 @@ +#+build freestanding +#+build js +package i18n +/* + Internationalization helpers. + + Copyright 2021-2022 Jeroen van Rijn . + Made available under Odin's license. + + List of contributors: + Jeroen van Rijn: Initial implementation. +*/ +import os "core:os/os2" + +@(private) +parse_qt :: proc { parse_qt_linguist_from_bytes } + +parse_mo :: proc { parse_mo_from_bytes } \ No newline at end of file diff --git a/core/text/i18n/i18n.odin b/core/text/i18n/i18n.odin index 8b107a8cd..148fe229f 100644 --- a/core/text/i18n/i18n.odin +++ b/core/text/i18n/i18n.odin @@ -8,8 +8,6 @@ package i18n List of contributors: Jeroen van Rijn: Initial implementation. */ -import "base:runtime" -import os "core:os/os2" import "core:strings" // Currently active catalog. @@ -231,13 +229,4 @@ destroy :: proc(catalog: ^Translation = ACTIVE, allocator := context.allocator) delete(catalog.k_v) strings.intern_destroy(&catalog.intern) free(catalog) -} - -@(private) -read_file :: proc(filename: string, allocator: runtime.Allocator) -> (data: []u8, err: Error) { - file_data, file_err := os.read_entire_file(filename, allocator) - if file_err != nil { - return {}, .File_Error - } - return file_data, nil } \ No newline at end of file diff --git a/core/text/i18n/i18n_os.odin b/core/text/i18n/i18n_os.odin new file mode 100644 index 000000000..db82a9cf6 --- /dev/null +++ b/core/text/i18n/i18n_os.odin @@ -0,0 +1,38 @@ +#+build !freestanding +#+build !js +package i18n +/* + Internationalization helpers. + + Copyright 2021-2022 Jeroen van Rijn . + Made available under Odin's license. + + List of contributors: + Jeroen van Rijn: Initial implementation. +*/ +import "base:runtime" +import os "core:os/os2" + +@(private) +read_file :: proc(filename: string, allocator: runtime.Allocator) -> (data: []u8, err: Error) { + file_data, file_err := os.read_entire_file(filename, allocator) + if file_err != nil { + return {}, .File_Error + } + return file_data, nil +} + +parse_qt_linguist_file :: proc(filename: string, options := DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) { + data := read_file(filename, allocator) or_return + return parse_qt_linguist_from_bytes(data, options, pluralizer, allocator) +} + +parse_qt :: proc { parse_qt_linguist_file, parse_qt_linguist_from_bytes } + +parse_mo_file :: proc(filename: string, options := DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) { + data := read_file(filename, allocator) or_return + defer delete(data) + return parse_mo_from_bytes(data, options, pluralizer, allocator) +} + +parse_mo :: proc { parse_mo_file, parse_mo_from_bytes } \ No newline at end of file diff --git a/core/text/i18n/qt_linguist.odin b/core/text/i18n/qt_linguist.odin index 78fe2712d..9c5791b67 100644 --- a/core/text/i18n/qt_linguist.odin +++ b/core/text/i18n/qt_linguist.odin @@ -154,9 +154,3 @@ parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTI return } -parse_qt_linguist_file :: proc(filename: string, options := DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) { - data := read_file(filename, allocator) or_return - return parse_qt_linguist_from_bytes(data, options, pluralizer, allocator) -} - -parse_qt :: proc { parse_qt_linguist_file, parse_qt_linguist_from_bytes } \ No newline at end of file diff --git a/core/text/regex/common/common.odin b/core/text/regex/common/common.odin index 24b44833f..cfbbe53ba 100644 --- a/core/text/regex/common/common.odin +++ b/core/text/regex/common/common.odin @@ -14,6 +14,8 @@ MAX_CAPTURE_GROUPS :: max(#config(ODIN_REGEX_MAX_CAPTURE_GROUPS, 10), 10) MAX_PROGRAM_SIZE :: int(max(i16)) MAX_CLASSES :: int(max(u8)) +ODIN_DEBUG_REGEX :: #config(ODIN_DEBUG_REGEX, false) + Flag :: enum u8 { // Multiline: treat `^` and `$` as if they also match newlines. Multiline, diff --git a/core/text/regex/common/debugging.odin b/core/text/regex/common/debugging.odin index e3fcb8b7e..055bbd20d 100644 --- a/core/text/regex/common/debugging.odin +++ b/core/text/regex/common/debugging.odin @@ -8,16 +8,9 @@ package regex_common Feoramund: Initial implementation. */ -@require import os "core:os/os2" import "core:io" import "core:strings" -ODIN_DEBUG_REGEX :: #config(ODIN_DEBUG_REGEX, false) - -when ODIN_DEBUG_REGEX { - debug_stream := os.stderr.stream -} - write_padded_hex :: proc(w: io.Writer, #any_int n, zeroes: int) { sb := strings.builder_make() defer strings.builder_destroy(&sb) diff --git a/core/text/regex/common/os.odin b/core/text/regex/common/os.odin new file mode 100644 index 000000000..1d38d687c --- /dev/null +++ b/core/text/regex/common/os.odin @@ -0,0 +1,17 @@ +#+build !freestanding +#+build !js +package regex_common + +/* + (c) Copyright 2024 Feoramund . + Made available under Odin's license. + + List of contributors: + Feoramund: Initial implementation. +*/ + +@require import os "core:os/os2" + +when ODIN_DEBUG_REGEX { + debug_stream := os.stderr.stream +} \ No newline at end of file diff --git a/core/text/table/utility.odin b/core/text/table/utility.odin index e361d0f5f..db5ae4602 100644 --- a/core/text/table/utility.odin +++ b/core/text/table/utility.odin @@ -1,3 +1,5 @@ +#+build !freestanding +#+build !js package text_table import "core:io" diff --git a/core/time/timezone/tz_os.odin b/core/time/timezone/tz_os.odin new file mode 100644 index 000000000..2ab7cfa6c --- /dev/null +++ b/core/time/timezone/tz_os.odin @@ -0,0 +1,19 @@ +#+build !freestanding +#+build !js +package timezone + +import os "core:os/os2" +import "core:time/datetime" + +load_tzif_file :: proc(filename: string, region_name: string, allocator := context.allocator) -> (out: ^datetime.TZ_Region, ok: bool) { + tzif_data, tzif_err := os.read_entire_file(filename, allocator) + if tzif_err != nil { + return nil, false + } + defer delete(tzif_data, allocator) + return parse_tzif(tzif_data, region_name, allocator) +} + +region_load_from_file :: proc(file_path, reg: string, allocator := context.allocator) -> (out_reg: ^datetime.TZ_Region, ok: bool) { + return load_tzif_file(file_path, reg, allocator) +} \ No newline at end of file diff --git a/core/time/timezone/tz_unix.odin b/core/time/timezone/tz_unix.odin index 32590f177..60a20e57c 100644 --- a/core/time/timezone/tz_unix.odin +++ b/core/time/timezone/tz_unix.odin @@ -14,7 +14,7 @@ local_tz_name :: proc(allocator := context.allocator) -> (name: string, success: path, err := os.get_absolute_path(orig_localtime_path, allocator) if err != nil { // If we can't find /etc/localtime, fallback to UTC - if err == .ENOENT { + if err == .Not_Exist { str, err2 := strings.clone("UTC", allocator) if err2 != nil { return } return str, true diff --git a/core/time/timezone/tzdate.odin b/core/time/timezone/tzdate.odin index f01553573..29e8ad25c 100644 --- a/core/time/timezone/tzdate.odin +++ b/core/time/timezone/tzdate.odin @@ -10,10 +10,6 @@ region_load :: proc(reg: string, allocator := context.allocator) -> (out_reg: ^ return _region_load(reg, allocator) } -region_load_from_file :: proc(file_path, reg: string, allocator := context.allocator) -> (out_reg: ^datetime.TZ_Region, ok: bool) { - return load_tzif_file(file_path, reg, allocator) -} - region_load_from_buffer :: proc(buffer: []u8, reg: string, allocator := context.allocator) -> (out_reg: ^datetime.TZ_Region, ok: bool) { return parse_tzif(buffer, reg, allocator) } diff --git a/core/time/timezone/tzif.odin b/core/time/timezone/tzif.odin index 7a7023c6c..3b92364ac 100644 --- a/core/time/timezone/tzif.odin +++ b/core/time/timezone/tzif.odin @@ -3,7 +3,6 @@ package timezone import "base:intrinsics" import "core:slice" import "core:strings" -import os "core:os/os2" import "core:strconv" import "core:time/datetime" @@ -67,16 +66,6 @@ tzif_data_block_size :: proc(hdr: ^TZif_Header, version: TZif_Version) -> (block int(hdr.isutcnt), true } - -load_tzif_file :: proc(filename: string, region_name: string, allocator := context.allocator) -> (out: ^datetime.TZ_Region, ok: bool) { - tzif_data, tzif_err := os.read_entire_file(filename, allocator) - if tzif_err != nil { - return nil, false - } - defer delete(tzif_data, allocator) - return parse_tzif(tzif_data, region_name, allocator) -} - @private is_alphabetic :: proc(ch: u8) -> bool { // ('A' -> 'Z') || ('a' -> 'z') diff --git a/examples/all/all_js.odin b/examples/all/all_js.odin index ee006ae86..bb7ed7fa1 100644 --- a/examples/all/all_js.odin +++ b/examples/all/all_js.odin @@ -10,7 +10,7 @@ package all @(require) import "core:compress" @(require) import "core:compress/shoco" -@(require) import "core:compress/gzip" +// @(require) import "core:compress/gzip" @(require) import "core:compress/zlib" @(require) import "core:container/avl" @@ -99,13 +99,13 @@ package all @(require) import "core:mem" @(require) import "core:mem/tlsf" -@(require) import "core:mem/virtual" +// Not supported on JS +// @(require) import "core:mem/virtual" @(require) import "core:odin/ast" @(require) import doc_format "core:odin/doc-format" @(require) import "core:odin/tokenizer" -@(require) import "core:os" @(require) import "core:path/slashpath" @(require) import "core:relative" @@ -130,6 +130,7 @@ package all @(require) import "core:text/match" @(require) import "core:text/regex" @(require) import "core:text/scanner" +// Not supported on JS, uses `core:mem/virtual`. @(require) import "core:text/table" @(require) import "core:thread" diff --git a/tests/core/time/test_core_time.odin b/tests/core/time/test_core_time.odin index cd2b19fb8..6e5e47696 100644 --- a/tests/core/time/test_core_time.odin +++ b/tests/core/time/test_core_time.odin @@ -2,6 +2,7 @@ package test_core_time import "core:testing" import "core:time" +@(require) import "core:log" import dt "core:time/datetime" import tz "core:time/timezone" @@ -364,9 +365,10 @@ test_convert_timezone_roundtrip :: proc(t: ^testing.T) { std_dt, _ := dt.components_to_datetime(2024, 11, 4, 23, 47, 0) local_tz, local_load_ok := tz.region_load("local") - testing.expectf(t, local_load_ok, "Failed to load local timezone") defer tz.region_destroy(local_tz) + testing.expectf(t, local_load_ok, "Failed to load local timezone") + edm_tz, edm_load_ok := tz.region_load("America/Edmonton") testing.expectf(t, edm_load_ok, "Failed to load America/Edmonton timezone") defer tz.region_destroy(edm_tz) -- cgit v1.2.3