io.odin 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. // package io provides basic interfaces for generic data stream primitives.
  2. // The purpose of this package is wrap existing data structures and their
  3. // operations into an abstracted stream interface.
  4. package io
  5. import "base:intrinsics"
  6. import "core:unicode/utf8"
  7. // Seek whence values
  8. Seek_From :: enum {
  9. Start = 0, // seek relative to the origin of the file
  10. Current = 1, // seek relative to the current offset
  11. End = 2, // seek relative to the end
  12. }
  13. Error :: enum i32 {
  14. // No Error
  15. None = 0,
  16. // EOF is the error returned by `read` when no more input is available
  17. EOF,
  18. // Unexpected_EOF means that EOF was encountered in the middle of reading a fixed-sized block of data
  19. Unexpected_EOF,
  20. // Short_Write means that a write accepted fewer bytes than requested but failed to return an explicit error
  21. Short_Write,
  22. // Invalid_Write means that a write returned an impossible count
  23. Invalid_Write,
  24. // Short_Buffer means that a read/write required a longer buffer than was provided
  25. Short_Buffer,
  26. // No_Progress is returned by some implementations of `io.Reader` when many calls
  27. // to `read` have failed to return any data or error.
  28. // This is usually a sign of a broken `io.Reader` implementation
  29. No_Progress,
  30. Invalid_Whence,
  31. Invalid_Offset,
  32. Invalid_Unread,
  33. Negative_Read,
  34. Negative_Write,
  35. Negative_Count,
  36. Buffer_Full,
  37. // Unknown means that an error has occurred but cannot be categorized
  38. Unknown,
  39. // Empty is returned when a procedure has not been implemented for an io.Stream
  40. Empty = -1,
  41. }
  42. Stream_Mode :: enum {
  43. Close,
  44. Flush,
  45. Read,
  46. Read_At,
  47. Write,
  48. Write_At,
  49. Seek,
  50. Size,
  51. Destroy,
  52. Query, // query what modes are available
  53. }
  54. Stream_Mode_Set :: distinct bit_set[Stream_Mode; i64]
  55. Stream_Proc :: #type proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offset: i64, whence: Seek_From) -> (n: i64, err: Error)
  56. Stream :: struct {
  57. procedure: Stream_Proc,
  58. data: rawptr,
  59. }
  60. Reader :: Stream
  61. Writer :: Stream
  62. Closer :: Stream
  63. Flusher :: Stream
  64. Seeker :: Stream
  65. Read_Writer :: Stream
  66. Read_Closer :: Stream
  67. Read_Write_Closer :: Stream
  68. Read_Write_Seeker :: Stream
  69. Write_Closer :: Stream
  70. Write_Seeker :: Stream
  71. Write_Flusher :: Stream
  72. Write_Flush_Closer :: Stream
  73. Reader_At :: Stream
  74. Writer_At :: Stream
  75. destroy :: proc(s: Stream) -> (err: Error) {
  76. _ = flush(s)
  77. _ = close(s)
  78. if s.procedure != nil {
  79. _, err = s.procedure(s.data, .Destroy, nil, 0, nil)
  80. } else {
  81. err = .Empty
  82. }
  83. return
  84. }
  85. query :: proc(s: Stream) -> (set: Stream_Mode_Set) {
  86. if s.procedure != nil {
  87. n, _ := s.procedure(s.data, .Query, nil, 0, nil)
  88. set = transmute(Stream_Mode_Set)n
  89. if set != nil {
  90. set += {.Query}
  91. }
  92. }
  93. return
  94. }
  95. query_utility :: #force_inline proc "contextless" (set: Stream_Mode_Set) -> (n: i64, err: Error) {
  96. return transmute(i64)set, nil
  97. }
  98. _i64_err :: #force_inline proc "contextless" (n: int, err: Error) -> (i64, Error) {
  99. return i64(n), err
  100. }
  101. // read reads up to len(p) bytes into s. It returns the number of bytes read and any error if occurred.
  102. //
  103. // When read encounters an .EOF or error after successfully reading n > 0 bytes, it returns the number of
  104. // bytes read along with the error.
  105. read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
  106. if s.procedure != nil {
  107. n64: i64
  108. n64, err = s.procedure(s.data, .Read, p, 0, nil)
  109. n = int(n64)
  110. if n_read != nil { n_read^ += n }
  111. } else {
  112. err = .Empty
  113. }
  114. return
  115. }
  116. // write writes up to len(p) bytes into s. It returns the number of bytes written and any error if occurred.
  117. write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Error) {
  118. if s.procedure != nil {
  119. n64: i64
  120. n64, err = s.procedure(s.data, .Write, p, 0, nil)
  121. n = int(n64)
  122. if n_written != nil { n_written^ += n }
  123. } else {
  124. err = .Empty
  125. }
  126. return
  127. }
  128. // seek sets the offset of the next read or write to offset.
  129. //
  130. // .Start means seek relative to the origin of the file.
  131. // .Current means seek relative to the current offset.
  132. // .End means seek relative to the end.
  133. //
  134. // seek returns the new offset to the start of the file/stream, and any error if occurred.
  135. seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
  136. if s.procedure != nil {
  137. n, err = s.procedure(s.data, .Seek, nil, offset, whence)
  138. } else {
  139. err = .Empty
  140. }
  141. return
  142. }
  143. // The behaviour of close after the first call is stream implementation defined.
  144. // Different streams may document their own behaviour.
  145. close :: proc(s: Closer) -> (err: Error) {
  146. if s.procedure != nil {
  147. _, err = s.procedure(s.data, .Close, nil, 0, nil)
  148. }
  149. return
  150. }
  151. flush :: proc(s: Flusher) -> (err: Error) {
  152. if s.procedure != nil {
  153. _, err = s.procedure(s.data, .Flush, nil, 0, nil)
  154. }
  155. return
  156. }
  157. // size returns the size of the stream. If the stream does not support querying its size, 0 will be returned.
  158. size :: proc(s: Stream) -> (n: i64, err: Error) {
  159. if s.procedure != nil {
  160. n, err = s.procedure(s.data, .Size, nil, 0, nil)
  161. if err == .Empty {
  162. n = 0
  163. curr := seek(s, 0, .Current) or_return
  164. end := seek(s, 0, .End) or_return
  165. seek(s, curr, .Start) or_return
  166. n = end
  167. }
  168. } else {
  169. err = .Empty
  170. }
  171. return
  172. }
  173. // read_at reads len(p) bytes into p starting with the provided offset in the underlying Reader_At stream r.
  174. // It returns the number of bytes read and any error if occurred.
  175. //
  176. // When read_at returns n < len(p), it returns a non-nil Error explaining why.
  177. //
  178. // If n == len(p), err may be either nil or .EOF
  179. read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n: int, err: Error) {
  180. if r.procedure != nil {
  181. n64: i64
  182. n64, err = r.procedure(r.data, .Read_At, p, offset, nil)
  183. if err != .Empty {
  184. n = int(n64)
  185. } else {
  186. curr := seek(r, offset, .Current) or_return
  187. n, err = read(r, p)
  188. _, err1 := seek(r, curr, .Start)
  189. if err1 != nil && err == nil {
  190. err = err1
  191. }
  192. }
  193. if n_read != nil { n_read^ += n }
  194. } else {
  195. err = .Empty
  196. }
  197. return
  198. }
  199. // write_at writes len(p) bytes into p starting with the provided offset in the underlying Writer_At stream w.
  200. // It returns the number of bytes written and any error if occurred.
  201. //
  202. // If write_at is writing to a Writer_At which has a seek offset, then write_at should not affect the underlying
  203. // seek offset.
  204. write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) {
  205. if w.procedure != nil {
  206. n64: i64
  207. n64, err = w.procedure(w.data, .Write_At, p, offset, nil)
  208. if err != .Empty {
  209. n = int(n64)
  210. } else {
  211. curr := seek(w, offset, .Current) or_return
  212. n, err = write(w, p)
  213. _, err1 := seek(w, curr, .Start)
  214. if err1 != nil && err == nil {
  215. err = err1
  216. }
  217. }
  218. if n_written != nil { n_written^ += n }
  219. } else {
  220. err = .Empty
  221. }
  222. return
  223. }
  224. // read_byte reads and returns the next byte from r.
  225. read_byte :: proc(r: Reader, n_read: ^int = nil) -> (b: byte, err: Error) {
  226. buf: [1]byte
  227. _, err = read(r, buf[:], n_read)
  228. b = buf[0]
  229. return
  230. }
  231. write_byte :: proc(w: Writer, c: byte, n_written: ^int = nil) -> Error {
  232. buf: [1]byte
  233. buf[0] = c
  234. write(w, buf[:], n_written) or_return
  235. return nil
  236. }
  237. // read_rune reads a single UTF-8 encoded Unicode codepoint and returns the rune and its size in bytes.
  238. read_rune :: proc(br: Reader, n_read: ^int = nil) -> (ch: rune, size: int, err: Error) {
  239. defer if err == nil && n_read != nil {
  240. n_read^ += size
  241. }
  242. b: [utf8.UTF_MAX]byte
  243. _, err = read(br, b[:1])
  244. s0 := b[0]
  245. ch = rune(s0)
  246. size = 1
  247. if err != nil {
  248. return
  249. }
  250. if ch < utf8.RUNE_SELF {
  251. return
  252. }
  253. x := utf8.accept_sizes[s0]
  254. if x >= 0xf0 {
  255. mask := rune(x) << 31 >> 31
  256. ch = ch &~ mask | utf8.RUNE_ERROR&mask
  257. return
  258. }
  259. sz := int(x&7)
  260. size, err = read(br, b[1:sz])
  261. if err != nil || size+1 < sz {
  262. ch = utf8.RUNE_ERROR
  263. return
  264. }
  265. ch, size = utf8.decode_rune(b[:sz])
  266. return
  267. }
  268. // write_string writes the contents of the string s to w.
  269. write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, err: Error) {
  270. return write(s, transmute([]byte)str, n_written)
  271. }
  272. // write_rune writes a UTF-8 encoded rune to w.
  273. write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err: Error) {
  274. defer if err == nil && n_written != nil {
  275. n_written^ += size
  276. }
  277. if r < utf8.RUNE_SELF {
  278. err = write_byte(s, byte(r))
  279. if err == nil {
  280. size = 1
  281. }
  282. return
  283. }
  284. buf, w := utf8.encode_rune(r)
  285. return write(s, buf[:w])
  286. }
  287. // read_full expected exactly len(buf) bytes from r into buf.
  288. read_full :: proc(r: Reader, buf: []byte) -> (n: int, err: Error) {
  289. return read_at_least(r, buf, len(buf))
  290. }
  291. // read_at_least reads from r into buf until it has read at least min bytes. It returns the number
  292. // of bytes copied and an error if fewer bytes were read. `.EOF` is only returned if no bytes were read.
  293. // `.Unexpected_EOF` is returned when an `.EOF ` is returned by the passed Reader after reading
  294. // fewer than min bytes. If len(buf) is less than min, `.Short_Buffer` is returned.
  295. read_at_least :: proc(r: Reader, buf: []byte, min: int) -> (n: int, err: Error) {
  296. if len(buf) < min {
  297. return 0, .Short_Buffer
  298. }
  299. for n < min && err == nil {
  300. nn: int
  301. nn, err = read(r, buf[n:])
  302. n += nn
  303. }
  304. if n >= min {
  305. err = nil
  306. } else if n > 0 && err == .EOF {
  307. err = .Unexpected_EOF
  308. }
  309. return
  310. }
  311. // write_full writes until the entire contents of `buf` has been written or an error occurs.
  312. write_full :: proc(w: Writer, buf: []byte) -> (n: int, err: Error) {
  313. return write_at_least(w, buf, len(buf))
  314. }
  315. // write_at_least writes at least `buf[:min]` to the writer and returns the amount written.
  316. // If an error occurs before writing everything it is returned.
  317. write_at_least :: proc(w: Writer, buf: []byte, min: int) -> (n: int, err: Error) {
  318. if len(buf) < min {
  319. return 0, .Short_Buffer
  320. }
  321. for n < min && err == nil {
  322. nn: int
  323. nn, err = write(w, buf[n:])
  324. n += nn
  325. }
  326. return
  327. }
  328. // copy copies from src to dst till either EOF is reached on src or an error occurs
  329. // It returns the number of bytes copied and the first error that occurred whilst copying, if any.
  330. copy :: proc(dst: Writer, src: Reader) -> (written: i64, err: Error) {
  331. return _copy_buffer(dst, src, nil)
  332. }
  333. // copy_buffer is the same as copy except that it stages through the provided buffer (if one is required)
  334. // rather than allocating a temporary one on the stack through `intrinsics.alloca`
  335. // If buf is `nil`, it is allocate through `intrinsics.alloca`; otherwise if it has zero length, it will panic
  336. copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err: Error) {
  337. if buf != nil && len(buf) == 0 {
  338. panic("empty buffer in io.copy_buffer")
  339. }
  340. return _copy_buffer(dst, src, buf)
  341. }
  342. // copy_n copies n bytes (or till an error) from src to dst.
  343. // It returns the number of bytes copied and the first error that occurred whilst copying, if any.
  344. // On return, written == n IFF err == nil
  345. copy_n :: proc(dst: Writer, src: Reader, n: i64) -> (written: i64, err: Error) {
  346. nsrc := limited_reader_init(&Limited_Reader{}, src, n)
  347. written, err = copy(dst, nsrc)
  348. if written == n {
  349. return n, nil
  350. }
  351. if written < n && err == nil {
  352. // src stopped early and must have been an EOF
  353. err = .EOF
  354. }
  355. return
  356. }
  357. @(private)
  358. _copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err: Error) {
  359. if dst.procedure == nil || src.procedure == nil {
  360. return 0, .Empty
  361. }
  362. buf := buf
  363. if buf == nil {
  364. DEFAULT_SIZE :: 4 * 1024
  365. size := DEFAULT_SIZE
  366. if src.procedure == _limited_reader_proc {
  367. l := (^Limited_Reader)(src.data)
  368. if i64(size) > l.n {
  369. if l.n < 1 {
  370. size = 1
  371. } else {
  372. size = int(l.n)
  373. }
  374. }
  375. }
  376. // NOTE(bill): alloca is fine here
  377. buf = intrinsics.alloca(size, 2*align_of(rawptr))[:size]
  378. }
  379. for {
  380. nr, er := read(src, buf)
  381. if nr > 0 {
  382. nw, ew := write(dst, buf[0:nr])
  383. if nw > 0 {
  384. written += i64(nw)
  385. }
  386. if ew != nil {
  387. err = ew
  388. break
  389. }
  390. if nr != nw {
  391. err = .Short_Write
  392. break
  393. }
  394. }
  395. if er != nil {
  396. if er != .EOF {
  397. err = er
  398. }
  399. break
  400. }
  401. }
  402. return
  403. }