123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- package strconv
- Int_Flag :: enum {
- Prefix,
- Plus,
- }
- 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 {
- switch bit_size {
- case 8:
- i := i8(u)
- neg = i < 0
- u = u64(abs(i64(i)))
- case 16:
- i := i16(u)
- neg = i < 0
- u = u64(abs(i64(i)))
- case 32:
- i := i32(u)
- neg = i < 0
- u = u64(abs(i64(i)))
- case 64:
- i := i64(u)
- neg = i < 0
- u = u64(abs(i))
- case:
- panic("is_integer_negative: Unknown integer size")
- }
- }
- 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")
- }
- a: [129]byte
- i := len(a)
- u, neg := is_integer_negative(x, is_signed, bit_size)
- b := u64(base)
- for u >= b {
- i-=1; a[i] = digits[u % b]
- u /= b
- }
- i-=1; a[i] = digits[u % b]
- if .Prefix in flags {
- ok := true
- switch base {
- case 2: i-=1; a[i] = 'b'
- case 8: i-=1; a[i] = 'o'
- // case 10: i-=1; a[i] = 'd';
- case 12: i-=1; a[i] = 'z'
- case 16: i-=1; a[i] = 'x'
- case: ok = false
- }
- if ok {
- i-=1; a[i] = '0'
- }
- }
- switch {
- case neg:
- i-=1; a[i] = '-'
- case .Plus in flags:
- i-=1; a[i] = '+'
- }
- out := a[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 {
- switch bit_size {
- case 8:
- i := i8(u)
- neg = i < 0
- u = u128(abs(i128(i)))
- case 16:
- i := i16(u)
- neg = i < 0
- u = u128(abs(i128(i)))
- case 32:
- i := i32(u)
- neg = i < 0
- u = u128(abs(i128(i)))
- case 64:
- i := i64(u)
- neg = i < 0
- u = u128(abs(i128(i)))
- case 128:
- i := i128(u)
- neg = i < 0
- u = u128(abs(i))
- case:
- panic("is_integer_negative: Unknown integer size")
- }
- }
- return
- }
- /*
- Appends the string representation of a 128-bit integer to a buffer with specified base, flags, and digit set.
- **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")
- }
- a: [140]byte
- i := len(a)
- u, neg := is_integer_negative_128(x, is_signed, bit_size)
- b := u128(base)
- for u >= b && i >= 0 {
- i-=1
- // rem: u128;
- // u = runtime.udivmod128(u, b, &rem);
- // u /= b;
- rem := u % b
- u /= b
- idx := u32(rem)
- a[i] = digits[idx]
- }
- i-=1; a[i] = digits[u64(u % b)]
- if .Prefix in flags {
- ok := true
- switch base {
- case 2: i-=1; a[i] = 'b'
- case 8: i-=1; a[i] = 'o'
- case 10: i-=1; a[i] = 'd'
- case 12: i-=1; a[i] = 'z'
- case 16: i-=1; a[i] = 'x'
- case: ok = false
- }
- if ok {
- i-=1; a[i] = '0'
- }
- }
- switch {
- case neg:
- i-=1; a[i] = '-'
- case .Plus in flags:
- i-=1; a[i] = '+'
- }
- out := a[i:]
- copy(buf, out)
- return string(buf[0:len(out)])
- }
|