writer.odin 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. package bufio
  2. import "core:io"
  3. import "core:mem"
  4. import "core:unicode/utf8"
  5. // import "core:bytes"
  6. // Writer is a buffered wrapper for an io.Writer
  7. Writer :: struct {
  8. buf: []byte,
  9. buf_allocator: mem.Allocator,
  10. wr: io.Writer,
  11. n: int,
  12. err: io.Error,
  13. max_consecutive_empty_writes: int,
  14. }
  15. writer_init :: proc(b: ^Writer, wr: io.Writer, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator) {
  16. size := size
  17. size = max(size, MIN_READ_BUFFER_SIZE)
  18. writer_reset(b, wr)
  19. b.buf_allocator = allocator
  20. b.buf = make([]byte, size, allocator)
  21. }
  22. writer_init_with_buf :: proc(b: ^Writer, wr: io.Writer, buf: []byte) {
  23. writer_reset(b, wr)
  24. b.buf_allocator = {}
  25. b.buf = buf
  26. }
  27. // writer_destroy destroys the underlying buffer with its associated allocator IFF that allocator has been set
  28. writer_destroy :: proc(b: ^Writer) {
  29. delete(b.buf, b.buf_allocator)
  30. b^ = {}
  31. }
  32. // writer_size returns the size of underlying buffer in bytes
  33. writer_size :: proc(b: ^Writer) -> int {
  34. return len(b.buf)
  35. }
  36. writer_reset :: proc(b: ^Writer, w: io.Writer) {
  37. b.wr = w
  38. b.n = 0
  39. b.err = nil
  40. }
  41. // writer_flush writes any buffered data into the underlying io.Writer
  42. writer_flush :: proc(b: ^Writer) -> io.Error {
  43. if b.err != nil {
  44. return b.err
  45. }
  46. if b.n == 0 {
  47. return nil
  48. }
  49. n, err := io.write(b.wr, b.buf[0:b.n])
  50. if n < b.n && err == nil {
  51. err = .Short_Write
  52. }
  53. if err != nil {
  54. if n > 0 && n < b.n {
  55. copy(b.buf[:b.n-n], b.buf[n : b.n])
  56. }
  57. b.n -= n
  58. b.err = err
  59. return err
  60. }
  61. b.n = 0
  62. return nil
  63. }
  64. // writer_available returns how many bytes are unused in the buffer
  65. writer_available :: proc(b: ^Writer) -> int {
  66. return len(b.buf) - b.n
  67. }
  68. // writer_buffered returns the number of bytes that have been writted into the current buffer
  69. writer_buffered :: proc(b: ^Writer) -> int {
  70. return b.n
  71. }
  72. // writer_write writes the contents of p into the buffer
  73. // It returns the number of bytes written
  74. // If n < len(p), it will return an error explaining why the write is short
  75. writer_write :: proc(b: ^Writer, p: []byte) -> (n: int, err: io.Error) {
  76. p := p
  77. for len(p) > writer_available(b) && b.err == nil {
  78. m: int
  79. if writer_buffered(b) == 0 {
  80. m, b.err = io.write(b.wr, p)
  81. } else {
  82. m = copy(b.buf[b.n:], p)
  83. b.n += m
  84. writer_flush(b)
  85. }
  86. n += m
  87. p = p[m:]
  88. }
  89. if b.err != nil {
  90. return n, b.err
  91. }
  92. m := copy(b.buf[b.n:], p)
  93. b.n += m
  94. m += n
  95. return m, nil
  96. }
  97. // writer_write_byte writes a single byte
  98. writer_write_byte :: proc(b: ^Writer, c: byte) -> io.Error {
  99. if b.err != nil {
  100. return b.err
  101. }
  102. if writer_available(b) <= 0 && writer_flush(b) != nil {
  103. return b.err
  104. }
  105. b.buf[b.n] = c
  106. b.n += 1
  107. return nil
  108. }
  109. // writer_write_rune writes a single unicode code point, and returns the number of bytes written with any error
  110. writer_write_rune :: proc(b: ^Writer, r: rune) -> (size: int, err: io.Error) {
  111. if r < utf8.RUNE_SELF {
  112. err = writer_write_byte(b, byte(r))
  113. size = 0 if err != nil else 1
  114. return
  115. }
  116. if b.err != nil {
  117. return 0, b.err
  118. }
  119. buf: [4]u8
  120. n := writer_available(b)
  121. if n < utf8.UTF_MAX {
  122. writer_flush(b)
  123. if b.err != nil {
  124. return 0, b.err
  125. }
  126. n = writer_available(b)
  127. if n < utf8.UTF_MAX {
  128. // this only happens if the buffer is very small
  129. w: int
  130. buf, w = utf8.encode_rune(r)
  131. return writer_write(b, buf[:w])
  132. }
  133. }
  134. buf, size = utf8.encode_rune(r)
  135. copy(b.buf[b.n:], buf[:size])
  136. b.n += size
  137. return
  138. }
  139. // writer_write writes a string into the buffer
  140. // It returns the number of bytes written
  141. // If n < len(p), it will return an error explaining why the write is short
  142. writer_write_string :: proc(b: ^Writer, s: string) -> (int, io.Error) {
  143. return writer_write(b, transmute([]byte)s)
  144. }
  145. // writer_read_from is to support io.Reader_From types
  146. // If the underlying writer supports the io,read_from, and b has no buffered data yet,
  147. // this procedure calls the underlying read_from implementation without buffering
  148. writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) {
  149. if b.err != nil {
  150. return 0, b.err
  151. }
  152. for {
  153. if writer_available(b) == 0 {
  154. writer_flush(b) or_return
  155. }
  156. if b.max_consecutive_empty_writes <= 0 {
  157. b.max_consecutive_empty_writes = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS
  158. }
  159. m: int
  160. nr := 0
  161. for nr < b.max_consecutive_empty_writes {
  162. m, err = io.read(r, b.buf[b.n:])
  163. if m != 0 || err != nil {
  164. break
  165. }
  166. nr += 1
  167. }
  168. if nr == b.max_consecutive_empty_writes {
  169. return n, .No_Progress
  170. }
  171. b.n += m
  172. n += i64(m)
  173. if err != nil {
  174. break
  175. }
  176. }
  177. if err == .EOF {
  178. if writer_available(b) == 0 {
  179. err = writer_flush(b)
  180. } else {
  181. err = nil
  182. }
  183. }
  184. return
  185. }
  186. // writer_to_stream converts a Writer into an io.Stream
  187. writer_to_stream :: proc(b: ^Writer) -> (s: io.Stream) {
  188. s.data = b
  189. s.procedure = _writer_proc
  190. return
  191. }
  192. // writer_to_stream converts a Writer into an io.Stream
  193. writer_to_writer :: proc(b: ^Writer) -> (s: io.Writer) {
  194. return writer_to_stream(b)
  195. }
  196. @(private)
  197. _writer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
  198. b := (^Writer)(stream_data)
  199. #partial switch mode {
  200. case .Flush:
  201. err = writer_flush(b)
  202. return
  203. case .Write:
  204. n_int: int
  205. n_int, err = writer_write(b, p)
  206. n = i64(n_int)
  207. return
  208. case .Destroy:
  209. writer_destroy(b)
  210. return
  211. case .Query:
  212. return io.query_utility({.Flush, .Write, .Destroy, .Query})
  213. }
  214. return 0, .Empty
  215. }