From b1e608bfba86fafb65825a8ac6028d72f0b9d134 Mon Sep 17 00:00:00 2001 From: Tetralux Date: Sun, 18 Feb 2024 14:46:21 +0000 Subject: [PATCH] [fmt] Add *printfln() Adds the following procedures, which just call through to the `printf` versions, with `newline = true`; a new parameter also added in this commit. In all cases, `wprintf` is the one that ultimately writes the newline, if requested. - printfln - fprintfln - eprintfln - aprintfln - tprintfln - bprintfln - caprintfln - ctprintfln - sbprintfln - wprintfln --- core/fmt/fmt.odin | 145 ++++++++++++++++++++++++++++++++++++------- core/fmt/fmt_os.odin | 24 ++++--- 2 files changed, 137 insertions(+), 32 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index a0d6d66d1..c840135ed 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -147,16 +147,30 @@ aprintln :: proc(args: ..any, sep := " ", allocator := context.allocator) -> str // *Allocates Using Context's Allocator* // // Inputs: +// - fmt: A format string with placeholders for the provided arguments. +// - args: A variadic list of arguments to be formatted. +// - newline: Whether the string should end with a newline. (See `aprintfln`.) +// +// Returns: A formatted string. The returned string must be freed accordingly. +// +aprintf :: proc(fmt: string, args: ..any, allocator := context.allocator, newline := false) -> string { + str: strings.Builder + strings.builder_init(&str, allocator) + sbprintf(&str, fmt, ..args, newline=newline) + return strings.to_string(str) +} +// Creates a formatted string using a format string and arguments, followed by a newline. +// +// *Allocates Using Context's Allocator* +// +// Inputs: // - fmt: A format string with placeholders for the provided arguments. // - args: A variadic list of arguments to be formatted. // // Returns: A formatted string. The returned string must be freed accordingly. // -aprintf :: proc(fmt: string, args: ..any, allocator := context.allocator) -> string { - str: strings.Builder - strings.builder_init(&str, allocator) - sbprintf(&str, fmt, ..args) - return strings.to_string(str) +aprintfln :: proc(fmt: string, args: ..any, allocator := context.allocator) -> string { + return aprintf(fmt, ..args, allocator=allocator, newline=true) } // Creates a formatted string // @@ -195,16 +209,30 @@ tprintln :: proc(args: ..any, sep := " ") -> string { // *Allocates Using Context's Temporary Allocator* // // Inputs: +// - fmt: A format string with placeholders for the provided arguments. +// - args: A variadic list of arguments to be formatted. +// - newline: Whether the string should end with a newline. (See `tprintfln`.) +// +// Returns: A formatted string. +// +tprintf :: proc(fmt: string, args: ..any, newline := false) -> string { + str: strings.Builder + strings.builder_init(&str, context.temp_allocator) + sbprintf(&str, fmt, ..args, newline=newline) + return strings.to_string(str) +} +// Creates a formatted string using a format string and arguments, followed by a newline. +// +// *Allocates Using Context's Temporary Allocator* +// +// Inputs: // - fmt: A format string with placeholders for the provided arguments. // - args: A variadic list of arguments to be formatted. // // Returns: A formatted string. // -tprintf :: proc(fmt: string, args: ..any) -> string { - str: strings.Builder - strings.builder_init(&str, context.temp_allocator) - sbprintf(&str, fmt, ..args) - return strings.to_string(str) +tprintfln :: proc(fmt: string, args: ..any) -> string { + return tprintf(fmt, ..args, newline=true) } // Creates a formatted string using a supplied buffer as the backing array. Writes into the buffer. // @@ -238,12 +266,25 @@ bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string { // - buf: The backing buffer // - fmt: A format string with placeholders for the provided arguments // - args: A variadic list of arguments to be formatted +// - newline: Whether the string should end with a newline. (See `bprintfln`.) // // Returns: A formatted string // -bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string { +bprintf :: proc(buf: []byte, fmt: string, args: ..any, newline := false) -> string { sb := strings.builder_from_bytes(buf) - return sbprintf(&sb, fmt, ..args) + return sbprintf(&sb, fmt, ..args, newline=newline) +} +// Creates a formatted string using a supplied buffer as the backing array, followed by a newline. Writes into the buffer. +// +// Inputs: +// - buf: The backing buffer +// - fmt: A format string with placeholders for the provided arguments +// - args: A variadic list of arguments to be formatted +// +// Returns: A formatted string +// +bprintfln :: proc(buf: []byte, fmt: string, args: ..any) -> string { + return bprintf(buf, fmt, ..args, newline=true) } // Runtime assertion with a formatted message // @@ -294,17 +335,31 @@ panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! { // Inputs: // - format: A format string with placeholders for the provided arguments // - args: A variadic list of arguments to be formatted +// - newline: Whether the string should end with a newline. (See `caprintfln`.) // // Returns: A formatted C string // -caprintf :: proc(format: string, args: ..any) -> cstring { +caprintf :: proc(format: string, args: ..any, newline := false) -> cstring { str: strings.Builder strings.builder_init(&str) - sbprintf(&str, format, ..args) + sbprintf(&str, format, ..args, newline=newline) strings.write_byte(&str, 0) s := strings.to_string(str) return cstring(raw_data(s)) } +// Creates a formatted C string, followed by a newline. +// +// *Allocates Using Context's Allocator* +// +// Inputs: +// - format: A format string with placeholders for the provided arguments +// - args: A variadic list of arguments to be formatted +// +// Returns: A formatted C string +// +caprintfln :: proc(format: string, args: ..any) -> cstring { + return caprintf(format, ..args, newline=true) +} // Creates a formatted C string // // *Allocates Using Context's Temporary Allocator* @@ -312,16 +367,30 @@ caprintf :: proc(format: string, args: ..any) -> cstring { // Inputs: // - format: A format string with placeholders for the provided arguments // - args: A variadic list of arguments to be formatted +// - newline: Whether the string should end with a newline. (See `ctprintfln`.) +// +// Returns: A formatted C string +// +ctprintf :: proc(format: string, args: ..any, newline := false) -> cstring { + str: strings.Builder + strings.builder_init(&str, context.temp_allocator) + sbprintf(&str, format, ..args, newline=newline) + strings.write_byte(&str, 0) + s := strings.to_string(str) + return cstring(raw_data(s)) +} +// Creates a formatted C string, followed by a newline. +// +// *Allocates Using Context's Temporary Allocator* +// +// Inputs: +// - format: A format string with placeholders for the provided arguments +// - args: A variadic list of arguments to be formatted // // Returns: A formatted C string // -ctprintf :: proc(format: string, args: ..any) -> cstring { - str: strings.Builder - strings.builder_init(&str, context.temp_allocator) - sbprintf(&str, format, ..args) - strings.write_byte(&str, 0) - s := strings.to_string(str) - return cstring(raw_data(s)) +ctprintfln :: proc(format: string, args: ..any) -> cstring { + return ctprintf(format, ..args, newline=true) } // Formats using the default print settings and writes to the given strings.Builder // @@ -355,13 +424,25 @@ sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string { // - buf: A pointer to a strings.Builder buffer // - fmt: The format string // - args: A variadic list of arguments to be formatted +// - newline: Whether a trailing newline should be written. (See `sbprintfln`.) // // Returns: The resulting formatted string // -sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string { - wprintf(strings.to_writer(buf), fmt, ..args, flush=true) +sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any, newline := false) -> string { + wprintf(strings.to_writer(buf), fmt, ..args, flush=true, newline=newline) return strings.to_string(buf^) } +// Formats and writes to a strings.Builder buffer according to the specified format string, followed by a newline. +// +// Inputs: +// - buf: A pointer to a strings.Builder to store the formatted string +// - args: A variadic list of arguments to be formatted +// +// Returns: A formatted string +// +sbprintfln :: proc(buf: ^strings.Builder, format: string, args: ..any) -> string { + return sbprintf(buf, format, ..args, newline=true) +} // Formats and writes to an io.Writer using the default print settings // // Inputs: @@ -435,10 +516,11 @@ wprintln :: proc(w: io.Writer, args: ..any, sep := " ", flush := true) -> int { // - w: An io.Writer to write to // - fmt: The format string // - args: A variadic list of arguments to be formatted +// - newline: Whether a trailing newline should be written. (See `wprintfln`.) // // Returns: The number of bytes written // -wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true) -> int { +wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true, newline := false) -> int { fi: Info arg_index: int = 0 end := len(fmt) @@ -708,12 +790,27 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true) -> int { } io.write_string(fi.writer, ")", &fi.n) } + + if newline { + io.write_byte(w, '\n', &fi.n) + } if flush { io.flush(w) } return fi.n } +// Formats and writes to an io.Writer according to the specified format string, followed by a newline. +// +// Inputs: +// - w: The io.Writer to write to. +// - args: A variadic list of arguments to be formatted. +// +// Returns: The number of bytes written. +// +wprintfln :: proc(w: io.Writer, format: string, args: ..any, flush := true) -> int { + return wprintf(w, format, ..args, flush=flush, newline=true) +} // Writes a ^runtime.Type_Info value to an io.Writer // // Inputs: diff --git a/core/fmt/fmt_os.odin b/core/fmt/fmt_os.odin index afc28ffff..a403dcd65 100644 --- a/core/fmt/fmt_os.odin +++ b/core/fmt/fmt_os.odin @@ -30,7 +30,7 @@ fprintln :: proc(fd: os.Handle, args: ..any, sep := " ", flush := true) -> int { return wprintln(w, ..args, sep=sep, flush=flush) } // fprintf formats according to the specified format string and writes to fd -fprintf :: proc(fd: os.Handle, fmt: string, args: ..any, flush := true) -> int { +fprintf :: proc(fd: os.Handle, fmt: string, args: ..any, flush := true, newline := false) -> int { buf: [1024]byte b: bufio.Writer defer bufio.writer_flush(&b) @@ -38,7 +38,11 @@ fprintf :: proc(fd: os.Handle, fmt: string, args: ..any, flush := true) -> int { bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:]) w := bufio.writer_to_writer(&b) - return wprintf(w, fmt, ..args, flush=flush) + return wprintf(w, fmt, ..args, flush=flush, newline=newline) +} +// fprintfln formats according to the specified format string and writes to fd, followed by a newline. +fprintfln :: proc(fd: os.Handle, fmt: string, args: ..any, flush := true) -> int { + return fprintf(fd, fmt, ..args, flush=flush, newline=true) } fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info, flush := true) -> (n: int, err: io.Error) { buf: [1024]byte @@ -62,15 +66,19 @@ fprint_typeid :: proc(fd: os.Handle, id: typeid, flush := true) -> (n: int, err: } // print formats using the default print settings and writes to os.stdout -print :: proc(args: ..any, sep := " ", flush := true) -> int { return fprint(os.stdout, ..args, sep=sep, flush=flush) } +print :: proc(args: ..any, sep := " ", flush := true) -> int { return fprint(os.stdout, ..args, sep=sep, flush=flush) } // println formats using the default print settings and writes to os.stdout -println :: proc(args: ..any, sep := " ", flush := true) -> int { return fprintln(os.stdout, ..args, sep=sep, flush=flush) } +println :: proc(args: ..any, sep := " ", flush := true) -> int { return fprintln(os.stdout, ..args, sep=sep, flush=flush) } // printf formats according to the specified format string and writes to os.stdout -printf :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(os.stdout, fmt, ..args, flush=flush) } +printf :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(os.stdout, fmt, ..args, flush=flush) } +// printfln formats according to the specified format string and writes to os.stdout, followed by a newline. +printfln :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(os.stdout, fmt, ..args, flush=flush, newline=true) } // eprint formats using the default print settings and writes to os.stderr -eprint :: proc(args: ..any, sep := " ", flush := true) -> int { return fprint(os.stderr, ..args, sep=sep, flush=flush) } +eprint :: proc(args: ..any, sep := " ", flush := true) -> int { return fprint(os.stderr, ..args, sep=sep, flush=flush) } // eprintln formats using the default print settings and writes to os.stderr -eprintln :: proc(args: ..any, sep := " ", flush := true) -> int { return fprintln(os.stderr, ..args, sep=sep, flush=flush) } +eprintln :: proc(args: ..any, sep := " ", flush := true) -> int { return fprintln(os.stderr, ..args, sep=sep, flush=flush) } // eprintf formats according to the specified format string and writes to os.stderr -eprintf :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(os.stderr, fmt, ..args, flush=flush) } +eprintf :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(os.stderr, fmt, ..args, flush=flush) } +// eprintfln formats according to the specified format string and writes to os.stderr, followed by a newline. +eprintfln :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(os.stderr, fmt, ..args, flush=flush, newline=true) }