mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-01 16:31:13 +00:00
Merge pull request #2421 from jon-lipstate/strconv_docs
Code Docs for strconv
This commit is contained in:
@@ -8,7 +8,17 @@ Decimal :: struct {
|
||||
decimal_point: int,
|
||||
neg, trunc: bool,
|
||||
}
|
||||
/*
|
||||
Sets a Decimal from a given string `s`. The string is expected to represent a float. Stores parsed number in the given Decimal structure.
|
||||
If parsing fails, the Decimal will be left in an undefined state.
|
||||
|
||||
**Inputs**
|
||||
- d: Pointer to a Decimal struct where the parsed result will be stored
|
||||
- s: The input string representing the floating-point number
|
||||
|
||||
**Returns**
|
||||
- ok: A boolean indicating whether the parsing was successful
|
||||
*/
|
||||
set :: proc(d: ^Decimal, s: string) -> (ok: bool) {
|
||||
d^ = {}
|
||||
|
||||
@@ -91,7 +101,16 @@ set :: proc(d: ^Decimal, s: string) -> (ok: bool) {
|
||||
|
||||
return i == len(s)
|
||||
}
|
||||
/*
|
||||
Converts a Decimal to a string representation, using the provided buffer as storage.
|
||||
|
||||
**Inputs**
|
||||
- buf: A byte slice buffer to hold the resulting string
|
||||
- a: The struct to be converted to a string
|
||||
|
||||
**Returns**
|
||||
- A string representation of the Decimal
|
||||
*/
|
||||
decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string {
|
||||
digit_zero :: proc(buf: []byte) -> int {
|
||||
for _, i in buf {
|
||||
@@ -100,7 +119,6 @@ decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string {
|
||||
return len(buf)
|
||||
}
|
||||
|
||||
|
||||
n := 10 + a.count + abs(a.decimal_point)
|
||||
|
||||
// TODO(bill): make this work with a buffer that's not big enough
|
||||
@@ -129,8 +147,12 @@ decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string {
|
||||
|
||||
return string(b[0:w])
|
||||
}
|
||||
/*
|
||||
Trims trailing zeros in the given Decimal, updating the count and decimal_point values as needed.
|
||||
|
||||
// trim trailing zeros
|
||||
**Inputs**
|
||||
- a: Pointer to the Decimal struct to be trimmed
|
||||
*/
|
||||
trim :: proc(a: ^Decimal) {
|
||||
for a.count > 0 && a.digits[a.count-1] == '0' {
|
||||
a.count -= 1
|
||||
@@ -139,8 +161,15 @@ trim :: proc(a: ^Decimal) {
|
||||
a.decimal_point = 0
|
||||
}
|
||||
}
|
||||
/*
|
||||
Converts a given u64 integer `idx` to its Decimal representation in the provided Decimal struct.
|
||||
|
||||
**Used for internal Decimal Operations.**
|
||||
|
||||
**Inputs**
|
||||
- a: Where the result will be stored
|
||||
- idx: The value to be assigned to the Decimal
|
||||
*/
|
||||
assign :: proc(a: ^Decimal, idx: u64) {
|
||||
buf: [64]byte
|
||||
n := 0
|
||||
@@ -160,9 +189,15 @@ assign :: proc(a: ^Decimal, idx: u64) {
|
||||
a.decimal_point = a.count
|
||||
trim(a)
|
||||
}
|
||||
/*
|
||||
Shifts the Decimal value to the right by k positions.
|
||||
|
||||
**Used for internal Decimal Operations.**
|
||||
|
||||
|
||||
**Inputs**
|
||||
- a: The Decimal struct to be shifted
|
||||
- k: The number of positions to shift right
|
||||
*/
|
||||
shift_right :: proc(a: ^Decimal, k: uint) {
|
||||
r := 0 // read index
|
||||
w := 0 // write index
|
||||
@@ -304,7 +339,15 @@ _shift_left_offsets := [?]struct{delta: int, cutoff: string}{
|
||||
{18, "173472347597680709441192448139190673828125"},
|
||||
{19, "867361737988403547205962240695953369140625"},
|
||||
}
|
||||
/*
|
||||
Shifts the decimal of the input value to the left by `k` places
|
||||
|
||||
WARNING: asserts `k < 61`
|
||||
|
||||
**Inputs**
|
||||
- a: The Decimal to be modified
|
||||
- k: The number of places to shift the decimal to the left
|
||||
*/
|
||||
shift_left :: proc(a: ^Decimal, k: uint) #no_bounds_check {
|
||||
prefix_less :: #force_inline proc "contextless" (b: []byte, s: string) -> bool #no_bounds_check {
|
||||
for i in 0..<len(s) {
|
||||
@@ -359,7 +402,13 @@ shift_left :: proc(a: ^Decimal, k: uint) #no_bounds_check {
|
||||
a.count = clamp(a.count, 0, len(a.digits))
|
||||
trim(a)
|
||||
}
|
||||
/*
|
||||
Shifts the decimal of the input value by the specified number of places
|
||||
|
||||
**Inputs**
|
||||
- a: The Decimal to be modified
|
||||
- i: The number of places to shift the decimal (positive for left shift, negative for right shift)
|
||||
*/
|
||||
shift :: proc(a: ^Decimal, i: int) {
|
||||
uint_size :: 8*size_of(uint)
|
||||
max_shift :: uint_size-4
|
||||
@@ -383,7 +432,15 @@ shift :: proc(a: ^Decimal, i: int) {
|
||||
shift_right(a, uint(-k))
|
||||
}
|
||||
}
|
||||
/*
|
||||
Determines if the Decimal can be rounded up at the given digit index
|
||||
|
||||
**Inputs**
|
||||
- a: The Decimal to check
|
||||
- nd: The digit index to consider for rounding up
|
||||
|
||||
**Returns** Boolean if can be rounded up at the given index (>=5)
|
||||
*/
|
||||
can_round_up :: proc(a: ^Decimal, nd: int) -> bool {
|
||||
if nd < 0 || nd >= a.count { return false }
|
||||
if a.digits[nd] == '5' && nd+1 == a.count {
|
||||
@@ -395,7 +452,13 @@ can_round_up :: proc(a: ^Decimal, nd: int) -> bool {
|
||||
|
||||
return a.digits[nd] >= '5'
|
||||
}
|
||||
/*
|
||||
Rounds the Decimal at the given digit index
|
||||
|
||||
**Inputs**
|
||||
- a: The Decimal to be modified
|
||||
- nd: The digit index to round
|
||||
*/
|
||||
round :: proc(a: ^Decimal, nd: int) {
|
||||
if nd < 0 || nd >= a.count { return }
|
||||
if can_round_up(a, nd) {
|
||||
@@ -404,7 +467,13 @@ round :: proc(a: ^Decimal, nd: int) {
|
||||
round_down(a, nd)
|
||||
}
|
||||
}
|
||||
/*
|
||||
Rounds the Decimal up at the given digit index
|
||||
|
||||
**Inputs**
|
||||
- a: The Decimal to be modified
|
||||
- nd: The digit index to round up
|
||||
*/
|
||||
round_up :: proc(a: ^Decimal, nd: int) {
|
||||
if nd < 0 || nd >= a.count { return }
|
||||
|
||||
@@ -421,15 +490,62 @@ round_up :: proc(a: ^Decimal, nd: int) {
|
||||
a.count = 1
|
||||
a.decimal_point += 1
|
||||
}
|
||||
/*
|
||||
Rounds down the decimal value to the specified number of decimal places
|
||||
|
||||
**Inputs**
|
||||
- a: The Decimal value to be rounded down
|
||||
- nd: The number of decimal places to round down to
|
||||
|
||||
Example:
|
||||
|
||||
import "core:fmt"
|
||||
import "core:strconv"
|
||||
|
||||
strconv_round_down_example :: proc {
|
||||
d: decimal.Decimal
|
||||
str := [64]u8{}
|
||||
ok := decimal.set(&d, "123.456")
|
||||
decimal.round_down(&d, 5)
|
||||
fmt.println(decimal.decimal_to_string(str[:], &d))
|
||||
}
|
||||
|
||||
Output:
|
||||
|
||||
123.45
|
||||
|
||||
*/
|
||||
round_down :: proc(a: ^Decimal, nd: int) {
|
||||
if nd < 0 || nd >= a.count { return }
|
||||
a.count = nd
|
||||
trim(a)
|
||||
}
|
||||
/*
|
||||
Extracts the rounded integer part of a decimal value
|
||||
|
||||
**Inputs**
|
||||
- a: A pointer to the Decimal value to extract the rounded integer part from
|
||||
|
||||
// Extract integer part, rounded appropriately. There are no guarantees about overflow.
|
||||
WARNING: There are no guarantees about overflow.
|
||||
|
||||
**Returns** The rounded integer part of the input decimal value
|
||||
|
||||
Example:
|
||||
|
||||
import "core:fmt"
|
||||
import "core:strconv"
|
||||
|
||||
strconv_rounded_integer_example :: proc {
|
||||
d: decimal.Decimal
|
||||
ok := decimal.set(&d, "123.456")
|
||||
fmt.println(decimal.rounded_integer(&d))
|
||||
}
|
||||
|
||||
Output:
|
||||
|
||||
123
|
||||
|
||||
*/
|
||||
rounded_integer :: proc(a: ^Decimal) -> u64 {
|
||||
if a.decimal_point > 20 {
|
||||
return 0xffff_ffff_ffff_ffff
|
||||
|
||||
@@ -20,7 +20,29 @@ _f16_info := Float_Info{10, 5, -15}
|
||||
_f32_info := Float_Info{23, 8, -127}
|
||||
_f64_info := Float_Info{52, 11, -1023}
|
||||
|
||||
/*
|
||||
Converts a floating-point number to a string with the specified format and precision.
|
||||
|
||||
**Inputs**
|
||||
|
||||
buf: A byte slice to store the resulting string
|
||||
val: The floating-point value to be converted
|
||||
fmt: The formatting byte, accepted values are 'e', 'E', 'f', 'F', 'g', 'G'
|
||||
precision: The number of decimal places to round to
|
||||
bit_size: The size of the floating-point number in bits, valid values are 16, 32, 64
|
||||
|
||||
Example:
|
||||
|
||||
buf: [32]byte
|
||||
val := 3.141592
|
||||
fmt := 'f'
|
||||
precision := 2
|
||||
bit_size := 64
|
||||
result := strconv.generic_ftoa(buf[:], val, fmt, precision, bit_size) -> "3.14"
|
||||
|
||||
**Returns**
|
||||
- A byte slice containing the formatted string
|
||||
*/
|
||||
generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, precision, bit_size: int) -> []byte {
|
||||
bits: u64
|
||||
flt: ^Float_Info
|
||||
@@ -95,8 +117,20 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, precision, bit_size: int)
|
||||
return format_digits(buf, shortest, neg, digs, prec, fmt)
|
||||
}
|
||||
|
||||
/*
|
||||
Converts a decimal floating-point number into a byte buffer with the given format
|
||||
|
||||
**Inputs**
|
||||
- buf: The byte buffer to store the formatted number
|
||||
- shortest: If true, generates the shortest representation of the number
|
||||
- neg: If true, the number is negative
|
||||
- digs: The decimal number to be formatted
|
||||
- precision: The number of digits after the decimal point
|
||||
- fmt: The format specifier (accepted values: 'f', 'F', 'e', 'E', 'g', 'G')
|
||||
|
||||
**Returns**
|
||||
- A byte slice containing the formatted decimal floating-point number
|
||||
*/
|
||||
format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slice, precision: int, fmt: byte) -> []byte {
|
||||
Buffer :: struct {
|
||||
b: []byte,
|
||||
@@ -217,7 +251,15 @@ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slic
|
||||
|
||||
|
||||
}
|
||||
/*
|
||||
Rounds the given decimal number to its shortest representation, considering the provided floating-point format
|
||||
|
||||
**Inputs**
|
||||
- d: The decimal number to round
|
||||
- mant: The mantissa of the floating-point number
|
||||
- exp: The exponent of the floating-point number
|
||||
- flt: Pointer to the Float_Info structure containing information about the floating-point format
|
||||
*/
|
||||
round_shortest :: proc(d: ^decimal.Decimal, mant: u64, exp: int, flt: ^Float_Info) {
|
||||
if mant == 0 { // If mantissa is zero, the number is zero
|
||||
d.count = 0
|
||||
@@ -284,7 +326,17 @@ round_shortest :: proc(d: ^decimal.Decimal, mant: u64, exp: int, flt: ^Float_Inf
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
Converts a decimal number to its floating-point representation with the given format and returns the resulting bits
|
||||
|
||||
**Inputs**
|
||||
- d: Pointer to the decimal number to convert
|
||||
- info: Pointer to the Float_Info structure containing information about the floating-point format
|
||||
|
||||
**Returns**
|
||||
- b: The bits representing the floating-point number
|
||||
- overflow: A boolean indicating whether an overflow occurred during conversion
|
||||
*/
|
||||
@(private)
|
||||
decimal_to_float_bits :: proc(d: ^decimal.Decimal, info: ^Float_Info) -> (b: u64, overflow: bool) {
|
||||
end :: proc "contextless" (d: ^decimal.Decimal, mant: u64, exp: int, info: ^Float_Info) -> (bits: u64) {
|
||||
|
||||
@@ -9,7 +9,18 @@ Int_Flags :: bit_set[Int_Flag]
|
||||
MAX_BASE :: 32
|
||||
digits := "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
/*
|
||||
Determines whether the given unsigned 64-bit integer is a negative value by interpreting it as a signed integer with the specified bit size.
|
||||
|
||||
**Inputs**
|
||||
- x: The unsigned 64-bit integer to check for negativity
|
||||
- is_signed: A boolean indicating if the input should be treated as a signed integer
|
||||
- bit_size: The bit size of the signed integer representation (8, 16, 32, or 64)
|
||||
|
||||
**Returns**
|
||||
- u: The absolute value of the input integer
|
||||
- neg: A boolean indicating whether the input integer is negative
|
||||
*/
|
||||
is_integer_negative :: proc(x: u64, is_signed: bool, bit_size: int) -> (u: u64, neg: bool) {
|
||||
u = x
|
||||
if is_signed {
|
||||
@@ -36,7 +47,21 @@ is_integer_negative :: proc(x: u64, is_signed: bool, bit_size: int) -> (u: u64,
|
||||
}
|
||||
return
|
||||
}
|
||||
/*
|
||||
Appends the string representation of an integer to a buffer with specified base, flags, and digit set.
|
||||
|
||||
**Inputs**
|
||||
- buf: The buffer to append the integer representation to
|
||||
- x: The integer value to convert
|
||||
- base: The base for the integer representation (2 <= base <= MAX_BASE)
|
||||
- is_signed: A boolean indicating if the input should be treated as a signed integer
|
||||
- bit_size: The bit size of the signed integer representation (8, 16, 32, or 64)
|
||||
- digits: The digit set used for the integer representation
|
||||
- flags: The Int_Flags bit set to control integer formatting
|
||||
|
||||
**Returns**
|
||||
- The string containing the integer representation appended to the buffer
|
||||
*/
|
||||
append_bits :: proc(buf: []byte, x: u64, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string {
|
||||
if base < 2 || base > MAX_BASE {
|
||||
panic("strconv: illegal base passed to append_bits")
|
||||
@@ -78,7 +103,18 @@ append_bits :: proc(buf: []byte, x: u64, base: int, is_signed: bool, bit_size: i
|
||||
copy(buf, out)
|
||||
return string(buf[0:len(out)])
|
||||
}
|
||||
/*
|
||||
Determines whether the given unsigned 128-bit integer is a negative value by interpreting it as a signed integer with the specified bit size.
|
||||
|
||||
**Inputs**
|
||||
- x: The unsigned 128-bit integer to check for negativity
|
||||
- is_signed: A boolean indicating if the input should be treated as a signed integer
|
||||
- bit_size: The bit size of the signed integer representation (8, 16, 32, 64, or 128)
|
||||
|
||||
**Returns**
|
||||
- u: The absolute value of the input integer
|
||||
- neg: A boolean indicating whether the input integer is negative
|
||||
*/
|
||||
is_integer_negative_128 :: proc(x: u128, is_signed: bool, bit_size: int) -> (u: u128, neg: bool) {
|
||||
u = x
|
||||
if is_signed {
|
||||
@@ -109,9 +145,21 @@ is_integer_negative_128 :: proc(x: u128, is_signed: bool, bit_size: int) -> (u:
|
||||
}
|
||||
return
|
||||
}
|
||||
/*
|
||||
Appends the string representation of a 128-bit integer to a buffer with specified base, flags, and digit set.
|
||||
|
||||
// import "core:runtime"
|
||||
**Inputs**
|
||||
- buf: The buffer to append the integer representation to
|
||||
- x: The 128-bit integer value to convert
|
||||
- base: The base for the integer representation (2 <= base <= MAX_BASE)
|
||||
- is_signed: A boolean indicating if the input should be treated as a signed integer
|
||||
- bit_size: The bit size of the signed integer representation (8, 16, 32, 64, or 128)
|
||||
- digits: The digit set used for the integer representation
|
||||
- flags: The Int_Flags bit set to control integer formatting
|
||||
|
||||
**Returns**
|
||||
- The string containing the integer representation appended to the buffer
|
||||
*/
|
||||
append_bits_128 :: proc(buf: []byte, x: u128, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string {
|
||||
if base < 2 || base > MAX_BASE {
|
||||
panic("strconv: illegal base passed to append_bits")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1081,7 +1081,6 @@ split_by_byte_iterator :: proc(s: ^string, sep: u8) -> (res: string, ok: bool) {
|
||||
}
|
||||
/*
|
||||
Splits the input string by the separator string in an iterator fashion.
|
||||
Destructively consumes the original string until the end.
|
||||
|
||||
Inputs:
|
||||
- s: Pointer to the input string, which is modified during the search.
|
||||
@@ -1116,7 +1115,6 @@ split_iterator :: proc(s: ^string, sep: string) -> (string, bool) {
|
||||
}
|
||||
/*
|
||||
Splits the input string after every separator string in an iterator fashion.
|
||||
Destructively consumes the original string until the end.
|
||||
|
||||
Inputs:
|
||||
- s: Pointer to the input string, which is modified during the search.
|
||||
|
||||
@@ -409,7 +409,7 @@ foreign kernel32 {
|
||||
// [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setfilecompletionnotificationmodes)
|
||||
SetFileCompletionNotificationModes :: proc(FileHandle: HANDLE, Flags: u8) -> BOOL ---
|
||||
// [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-createiocompletionport)
|
||||
CreateIoCompletionPort :: proc(FileHandle: HANDLE, ExistingCompletionPort: HANDLE, CompletionKey: uintptr, NumberOfConcurrentThreads: DWORD) -> HANDLE ---
|
||||
CreateIoCompletionPort :: proc(FileHandle: HANDLE, ExistingCompletionPort: HANDLE, CompletionKey: ^uintptr, NumberOfConcurrentThreads: DWORD) -> HANDLE ---
|
||||
//[MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-getqueuedcompletionstatus)
|
||||
GetQueuedCompletionStatus :: proc(CompletionPort: HANDLE, lpNumberOfBytesTransferred: ^DWORD, lpCompletionKey: uintptr, lpOverlapped: ^^OVERLAPPED, dwMilliseconds: DWORD) -> BOOL ---
|
||||
// [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-getqueuedcompletionstatusex)
|
||||
|
||||
Reference in New Issue
Block a user