code wiki / (root) / nx_bytes_fmt.nx

nx_bytes_fmt.nx source

↩ module page · 131 lines · 4114 B

1// bytes_fmt.nx -- human-readable byte-size formatter. 2// 3// Renders byte counts as "1.2 KB" / "5.3 MB" / "12.0 GB" for 4// logs + UI. Binary (1024-based, KiB/MiB/GiB) + decimal (1000- 5// based, KB/MB/GB) variants both provided. 6// 7// Used by: fs stat reporters, HTTP Content-Length logs, storage 8// quota displays. 9// 10// Invariants: 11// BF1 Output is deterministic: same input bytes -> same output. 12// BF2 Always produces exactly one significant decimal digit 13// (unless the unit is B, where decimals make no sense). 14// BF3 Negative byte counts produce "-<formatted>" (only the 15// magnitude is unit-scaled). 16 17// nx_safety_envelope: 18// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 19// sil_target: SIL1 20// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 21// verdict: NOT_YET_EVALUATED 22 23import "nx_syscalls.nx" 24const K_MAGIC_1024: i64 = 1024 25const K_MAGIC_2048: i64 = 2048 26 27// Emit decimal integer into out starting at pos. Returns digits 28// written. Used by both variants. 29func bf_emit_uint(out: *u8, pos: i64, n: i64) -> i64 { 30 if n == 0 { 31 out[pos] = 0x30 32 return 1 33 } 34 let buf: *u8 = sys_mmap(32) 35 var v: i64 = n 36 var k: i64 = 0 37 while v > 0 { 38 buf[k] = 0x30 + (v % 10) 39 v = v / 10 40 k = k + 1 41 } 42 var i: i64 = 0 43 while i < k { 44 out[pos + i] = buf[k - 1 - i] 45 i = i + 1 46 } 47 return k 48} 49 50// Shared formatter: writes "<whole>.<tenth> <unit>" to out starting 51// at pos. `scale` = 1024 (binary) or 1000 (decimal). 52// Returns total bytes written. 53func bf_fmt_scaled(bytes: i64, scale: i64, binary_units: i64, 54 out: *u8, pos: i64) -> i64 { 55 var p: i64 = pos 56 var abs: i64 = bytes 57 if abs < 0 { 58 out[p] = 0x2D // '-' 59 p = p + 1 60 abs = 0 - abs 61 } 62 // Select unit by order-of-magnitude. 63 var value: i64 = abs 64 var remainder: i64 = 0 65 var unit: i64 = 0 // 0 = B, 1 = K, 2 = M, 3 = G, 4 = T, 5 = P 66 while value >= scale { 67 remainder = value % scale 68 value = value / scale 69 unit = unit + 1 70 if unit >= 5 { unit = 5 } 71 } 72 73 // Whole part. 74 p = p + bf_emit_uint(out, p, value) 75 76 // Fractional part: one digit = (remainder * 10) / scale. 77 // Only for non-byte units. 78 if unit > 0 { 79 out[p] = 0x2E // '.' 80 p = p + 1 81 let tenth: i64 = (remainder * 10) / scale 82 out[p] = 0x30 + tenth 83 p = p + 1 84 } 85 86 // Space + unit suffix. 87 out[p] = 0x20 88 p = p + 1 89 if unit == 0 { out[p] = 0x42; p = p + 1; return p - pos } // "B" 90 // Unit letter. 91 if unit == 1 { out[p] = 0x4B; p = p + 1 } // 'K' 92 if unit == 2 { out[p] = 0x4D; p = p + 1 } // 'M' 93 if unit == 3 { out[p] = 0x47; p = p + 1 } // 'G' 94 if unit == 4 { out[p] = 0x54; p = p + 1 } // 'T' 95 if unit == 5 { out[p] = 0x50; p = p + 1 } // 'P' 96 if binary_units == 1 { 97 out[p] = 0x69 // 'i' -- KiB/MiB 98 p = p + 1 99 } 100 out[p] = 0x42 // 'B' 101 p = p + 1 102 return p - pos 103} 104 105// Binary (1024-based, KiB / MiB / GiB). Preferred for storage 106// display. 107func bytes_fmt_binary(bytes: i64, out: *u8, pos: i64) -> i64 { 108 return bf_fmt_scaled(bytes, K_MAGIC_1024, 1, out, pos) 109} 110 111// Decimal (1000-based, KB / MB / GB). Preferred for marketing / 112// network throughput reporting (matches vendor specs). 113func bytes_fmt_decimal(bytes: i64, out: *u8, pos: i64) -> i64 { 114 return bf_fmt_scaled(bytes, 1000, 0, out, pos) 115} 116 117// Compile-only smoke: 2048 bytes -> "2.0 KiB" (binary) or 118// "2.0 KB" (decimal)... actually 2048 / 1000 = 2, remainder 48; 119// tenth = 480/1000 = 0 -> "2.0 KB". 120func main() -> i64 { 121 let out: *u8 = sys_mmap(32) 122 let n: i64 = bytes_fmt_binary(K_MAGIC_2048, out, 0) 123 // "2.0 KiB" = 7 chars 124 if n != 7 { return 1 } 125 if out[0] != 0x32 { return 2 } // '2' 126 if out[1] != 0x2E { return 3 } // '.' 127 if out[4] != 0x4B { return 4 } // 'K' 128 if out[5] != 0x69 { return 5 } // 'i' 129 if out[6] != 0x42 { return 6 } // 'B' 130 return 0 131}