util.odin 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. package io
  2. import "core:strconv"
  3. import "core:unicode/utf8"
  4. import "core:unicode/utf16"
  5. read_ptr :: proc(r: Reader, p: rawptr, byte_size: int, n_read: ^int = nil) -> (n: int, err: Error) {
  6. return read(r, ([^]byte)(p)[:byte_size], n_read)
  7. }
  8. write_ptr :: proc(w: Writer, p: rawptr, byte_size: int, n_written: ^int = nil) -> (n: int, err: Error) {
  9. return write(w, ([^]byte)(p)[:byte_size], n_written)
  10. }
  11. read_ptr_at :: proc(r: Reader_At, p: rawptr, byte_size: int, offset: i64, n_read: ^int = nil) -> (n: int, err: Error) {
  12. return read_at(r, ([^]byte)(p)[:byte_size], offset, n_read)
  13. }
  14. write_ptr_at :: proc(w: Writer_At, p: rawptr, byte_size: int, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) {
  15. return write_at(w, ([^]byte)(p)[:byte_size], offset, n_written)
  16. }
  17. write_u64 :: proc(w: Writer, i: u64, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
  18. buf: [32]byte
  19. s := strconv.append_bits(buf[:], i, base, false, 64, strconv.digits, nil)
  20. return write_string(w, s, n_written)
  21. }
  22. write_i64 :: proc(w: Writer, i: i64, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
  23. buf: [32]byte
  24. s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil)
  25. return write_string(w, s, n_written)
  26. }
  27. write_uint :: proc(w: Writer, i: uint, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
  28. return write_u64(w, u64(i), base, n_written)
  29. }
  30. write_int :: proc(w: Writer, i: int, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
  31. return write_i64(w, i64(i), base, n_written)
  32. }
  33. write_u128 :: proc(w: Writer, i: u128, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
  34. buf: [39]byte
  35. s := strconv.append_bits_128(buf[:], i, base, false, 128, strconv.digits, nil)
  36. return write_string(w, s, n_written)
  37. }
  38. write_i128 :: proc(w: Writer, i: i128, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
  39. buf: [40]byte
  40. s := strconv.append_bits_128(buf[:], u128(i), base, true, 128, strconv.digits, nil)
  41. return write_string(w, s, n_written)
  42. }
  43. write_f16 :: proc(w: Writer, val: f16, n_written: ^int = nil) -> (n: int, err: Error) {
  44. buf: [386]byte
  45. str := strconv.append_float(buf[1:], f64(val), 'f', 2*size_of(val), 8*size_of(val))
  46. s := buf[:len(str)+1]
  47. if s[1] == '+' || s[1] == '-' {
  48. s = s[1:]
  49. } else {
  50. s[0] = '+'
  51. }
  52. if s[0] == '+' {
  53. s = s[1:]
  54. }
  55. return write_string(w, string(s), n_written)
  56. }
  57. write_f32 :: proc(w: Writer, val: f32, n_written: ^int = nil) -> (n: int, err: Error) {
  58. buf: [386]byte
  59. str := strconv.append_float(buf[1:], f64(val), 'f', 2*size_of(val), 8*size_of(val))
  60. s := buf[:len(str)+1]
  61. if s[1] == '+' || s[1] == '-' {
  62. s = s[1:]
  63. } else {
  64. s[0] = '+'
  65. }
  66. if s[0] == '+' {
  67. s = s[1:]
  68. }
  69. return write_string(w, string(s), n_written)
  70. }
  71. write_f64 :: proc(w: Writer, val: f64, n_written: ^int = nil) -> (n: int, err: Error) {
  72. buf: [386]byte
  73. str := strconv.append_float(buf[1:], val, 'f', 2*size_of(val), 8*size_of(val))
  74. s := buf[:len(str)+1]
  75. if s[1] == '+' || s[1] == '-' {
  76. s = s[1:]
  77. } else {
  78. s[0] = '+'
  79. }
  80. if s[0] == '+' {
  81. s = s[1:]
  82. }
  83. return write_string(w, string(s), n_written)
  84. }
  85. @(private="file")
  86. DIGITS_LOWER := "0123456789abcdefx"
  87. n_wrapper :: proc(n: int, err: Error, bytes_processed: ^int) -> Error {
  88. bytes_processed^ += n
  89. return err
  90. }
  91. write_encoded_rune :: proc(w: Writer, r: rune, write_quote := true, n_written: ^int = nil) -> (n: int, err: Error) {
  92. defer if n_written != nil {
  93. n_written^ += n
  94. }
  95. if write_quote {
  96. write_byte(w, '\'', &n) or_return
  97. }
  98. switch r {
  99. case '\a': write_string(w, `\a`, &n) or_return
  100. case '\b': write_string(w, `\b`, &n) or_return
  101. case '\e': write_string(w, `\e`, &n) or_return
  102. case '\f': write_string(w, `\f`, &n) or_return
  103. case '\n': write_string(w, `\n`, &n) or_return
  104. case '\r': write_string(w, `\r`, &n) or_return
  105. case '\t': write_string(w, `\t`, &n) or_return
  106. case '\v': write_string(w, `\v`, &n) or_return
  107. case:
  108. if r < 32 {
  109. write_string(w, `\x`, &n) or_return
  110. buf: [2]byte
  111. s := strconv.append_bits(buf[:], u64(r), 16, true, 64, strconv.digits, nil)
  112. switch len(s) {
  113. case 0: write_string(w, "00", &n) or_return
  114. case 1: write_byte(w, '0', &n) or_return
  115. case 2: write_string(w, s, &n) or_return
  116. }
  117. } else {
  118. write_rune(w, r, &n) or_return
  119. }
  120. }
  121. if write_quote {
  122. write_byte(w, '\'', &n) or_return
  123. }
  124. return
  125. }
  126. write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false, n_written: ^int = nil, for_json := false) -> (n: int, err: Error) {
  127. is_printable :: proc(r: rune) -> bool {
  128. if r <= 0xff {
  129. switch r {
  130. case 0x20..=0x7e:
  131. return true
  132. case 0xa1..=0xff: // ¡ through ÿ except for the soft hyphen
  133. return r != 0xad //
  134. }
  135. }
  136. // TODO(bill): A proper unicode library will be needed!
  137. return false
  138. }
  139. defer if n_written != nil {
  140. n_written^ += n
  141. }
  142. if html_safe {
  143. switch r {
  144. case '<', '>', '&':
  145. write_byte(w, '\\', &n) or_return
  146. write_byte(w, 'u', &n) or_return
  147. for s := 12; s >= 0; s -= 4 {
  148. write_byte(w, DIGITS_LOWER[r>>uint(s) & 0xf], &n) or_return
  149. }
  150. return
  151. }
  152. }
  153. if r == rune(quote) || r == '\\' {
  154. write_byte(w, '\\', &n) or_return
  155. write_byte(w, byte(r), &n) or_return
  156. return
  157. } else if is_printable(r) {
  158. write_encoded_rune(w, r, false, &n) or_return
  159. return
  160. }
  161. switch r {
  162. case '\a': write_string(w, `\a`, &n) or_return
  163. case '\b': write_string(w, `\b`, &n) or_return
  164. case '\e': write_string(w, `\e`, &n) or_return
  165. case '\f': write_string(w, `\f`, &n) or_return
  166. case '\n': write_string(w, `\n`, &n) or_return
  167. case '\r': write_string(w, `\r`, &n) or_return
  168. case '\t': write_string(w, `\t`, &n) or_return
  169. case '\v': write_string(w, `\v`, &n) or_return
  170. case:
  171. switch c := r; {
  172. case c < ' ':
  173. write_byte(w, '\\', &n) or_return
  174. write_byte(w, 'x', &n) or_return
  175. write_byte(w, DIGITS_LOWER[byte(c)>>4], &n) or_return
  176. write_byte(w, DIGITS_LOWER[byte(c)&0xf], &n) or_return
  177. case c > utf8.MAX_RUNE:
  178. c = 0xfffd
  179. fallthrough
  180. case c < 0x10000:
  181. write_byte(w, '\\', &n) or_return
  182. write_byte(w, 'u', &n) or_return
  183. for s := 12; s >= 0; s -= 4 {
  184. write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
  185. }
  186. case:
  187. if for_json {
  188. buf: [2]u16
  189. utf16.encode(buf[:], []rune{c})
  190. for bc in buf {
  191. write_byte(w, '\\', &n) or_return
  192. write_byte(w, 'u', &n) or_return
  193. for s := 12; s >= 0; s -= 4 {
  194. write_byte(w, DIGITS_LOWER[bc>>uint(s) & 0xf], &n) or_return
  195. }
  196. }
  197. } else {
  198. write_byte(w, '\\', &n) or_return
  199. write_byte(w, 'U', &n) or_return
  200. for s := 24; s >= 0; s -= 4 {
  201. write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
  202. }
  203. }
  204. }
  205. }
  206. return
  207. }
  208. write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written: ^int = nil, for_json := false) -> (n: int, err: Error) {
  209. defer if n_written != nil {
  210. n_written^ += n
  211. }
  212. write_byte(w, quote, &n) or_return
  213. for width, s := 0, str; len(s) > 0; s = s[width:] {
  214. r := rune(s[0])
  215. width = 1
  216. if r >= utf8.RUNE_SELF {
  217. r, width = utf8.decode_rune_in_string(s)
  218. }
  219. if width == 1 && r == utf8.RUNE_ERROR {
  220. write_byte(w, '\\', &n) or_return
  221. write_byte(w, 'x', &n) or_return
  222. write_byte(w, DIGITS_LOWER[s[0]>>4], &n) or_return
  223. write_byte(w, DIGITS_LOWER[s[0]&0xf], &n) or_return
  224. continue
  225. }
  226. n_wrapper(write_escaped_rune(w, r, quote, false, nil, for_json), &n) or_return
  227. }
  228. write_byte(w, quote, &n) or_return
  229. return
  230. }
  231. // writer append a quoted rune into the byte buffer, return the written size
  232. write_quoted_rune :: proc(w: Writer, r: rune) -> (n: int) {
  233. _write_byte :: #force_inline proc(w: Writer, c: byte) -> int {
  234. err := write_byte(w, c)
  235. return 1 if err == nil else 0
  236. }
  237. quote := byte('\'')
  238. n += _write_byte(w, quote)
  239. buf, width := utf8.encode_rune(r)
  240. if width == 1 && r == utf8.RUNE_ERROR {
  241. n += _write_byte(w, '\\')
  242. n += _write_byte(w, 'x')
  243. n += _write_byte(w, DIGITS_LOWER[buf[0]>>4])
  244. n += _write_byte(w, DIGITS_LOWER[buf[0]&0xf])
  245. } else {
  246. i, _ := write_escaped_rune(w, r, quote)
  247. n += i
  248. }
  249. n += _write_byte(w, quote)
  250. return
  251. }
  252. Tee_Reader :: struct {
  253. r: Reader,
  254. w: Writer,
  255. }
  256. @(private)
  257. _tee_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
  258. t := (^Tee_Reader)(stream_data)
  259. #partial switch mode {
  260. case .Read:
  261. n, err = _i64_err(read(t.r, p))
  262. if n > 0 {
  263. if wn, werr := write(t.w, p[:n]); werr != nil {
  264. return i64(wn), werr
  265. }
  266. }
  267. return
  268. case .Query:
  269. return query_utility({.Read, .Query})
  270. }
  271. return 0, .Empty
  272. }
  273. // tee_reader_init returns a Reader that writes to 'w' what it reads from 'r'
  274. // All reads from 'r' performed through it are matched with a corresponding write to 'w'
  275. // There is no internal buffering done
  276. // The write must complete before th read completes
  277. // Any error encountered whilst writing is reported as a 'read' error
  278. // tee_reader_init must call io.destroy when done with
  279. tee_reader_init :: proc(t: ^Tee_Reader, r: Reader, w: Writer, allocator := context.allocator) -> Reader {
  280. t.r, t.w = r, w
  281. return tee_reader_to_reader(t)
  282. }
  283. tee_reader_to_reader :: proc(t: ^Tee_Reader) -> (r: Reader) {
  284. r.data = t
  285. r.procedure = _tee_reader_proc
  286. return
  287. }
  288. // A Limited_Reader reads from r but limits the amount of data returned to just n bytes.
  289. // Each call to read updates n to reflect the new amount remaining.
  290. // read returns EOF when n <= 0 or when the underlying r returns EOF.
  291. Limited_Reader :: struct {
  292. r: Reader, // underlying reader
  293. n: i64, // max_bytes
  294. }
  295. @(private)
  296. _limited_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
  297. l := (^Limited_Reader)(stream_data)
  298. #partial switch mode {
  299. case .Read:
  300. if l.n <= 0 {
  301. return 0, .EOF
  302. }
  303. p := p
  304. if i64(len(p)) > l.n {
  305. p = p[0:l.n]
  306. }
  307. n, err = _i64_err(read(l.r, p))
  308. l.n -= i64(n)
  309. return
  310. case .Query:
  311. return query_utility({.Read, .Query})
  312. }
  313. return 0, .Empty
  314. }
  315. limited_reader_init :: proc(l: ^Limited_Reader, r: Reader, n: i64) -> Reader {
  316. l.r = r
  317. l.n = n
  318. return limited_reader_to_reader(l)
  319. }
  320. limited_reader_to_reader :: proc(l: ^Limited_Reader) -> (r: Reader) {
  321. r.procedure = _limited_reader_proc
  322. r.data = l
  323. return
  324. }
  325. // Section_Reader implements read, seek, and read_at on a section of an underlying Reader_At
  326. Section_Reader :: struct {
  327. r: Reader_At,
  328. base: i64,
  329. off: i64,
  330. limit: i64,
  331. }
  332. section_reader_init :: proc(s: ^Section_Reader, r: Reader_At, off: i64, n: i64) {
  333. s.r = r
  334. s.off = off
  335. s.limit = off + n
  336. return
  337. }
  338. section_reader_to_stream :: proc(s: ^Section_Reader) -> (out: Stream) {
  339. out.data = s
  340. out.procedure = _section_reader_proc
  341. return
  342. }
  343. @(private)
  344. _section_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
  345. s := (^Section_Reader)(stream_data)
  346. #partial switch mode {
  347. case .Read:
  348. if s.off >= s.limit {
  349. return 0, .EOF
  350. }
  351. p := p
  352. if max := s.limit - s.off; i64(len(p)) > max {
  353. p = p[0:max]
  354. }
  355. n, err = _i64_err(read_at(s.r, p, s.off))
  356. s.off += i64(n)
  357. return
  358. case .Read_At:
  359. p, off := p, offset
  360. if off < 0 || off >= s.limit - s.base {
  361. return 0, .EOF
  362. }
  363. off += s.base
  364. if max := s.limit - off; i64(len(p)) > max {
  365. p = p[0:max]
  366. n, err = _i64_err(read_at(s.r, p, off))
  367. if err == nil {
  368. err = .EOF
  369. }
  370. return
  371. }
  372. return _i64_err(read_at(s.r, p, off))
  373. case .Seek:
  374. offset := offset
  375. switch whence {
  376. case:
  377. return 0, .Invalid_Whence
  378. case .Start:
  379. offset += s.base
  380. case .Current:
  381. offset += s.off
  382. case .End:
  383. offset += s.limit
  384. }
  385. if offset < s.base {
  386. return 0, .Invalid_Offset
  387. }
  388. s.off = offset
  389. n = offset - s.base
  390. return
  391. case .Size:
  392. n = s.limit - s.base
  393. return
  394. case .Query:
  395. return query_utility({.Read, .Read_At, .Seek, .Size, .Query})
  396. }
  397. return 0, nil
  398. }