reader.odin 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. package strings
  2. import "core:io"
  3. import "core:unicode/utf8"
  4. /*
  5. io stream data for a string reader that can read based on bytes or runes
  6. implements the vtable when using the `io.Reader` variants
  7. "read" calls advance the current reading offset `i`
  8. */
  9. Reader :: struct {
  10. s: string, // read-only buffer
  11. i: i64, // current reading index
  12. prev_rune: int, // previous reading index of rune or < 0
  13. }
  14. /*
  15. Initializes a string Reader with the provided string
  16. Inputs:
  17. - r: A pointer to a Reader struct
  18. - s: The input string to be read
  19. */
  20. reader_init :: proc(r: ^Reader, s: string) {
  21. r.s = s
  22. r.i = 0
  23. r.prev_rune = -1
  24. }
  25. /*
  26. Converts a Reader into an `io.Stream`
  27. Inputs:
  28. - r: A pointer to a Reader struct
  29. Returns:
  30. - s: An io.Stream for the given Reader
  31. */
  32. reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
  33. s.data = r
  34. s.procedure = _reader_proc
  35. return
  36. }
  37. /*
  38. Initializes a string Reader and returns an `io.Reader` for the given string
  39. Inputs:
  40. - r: A pointer to a Reader struct
  41. - s: The input string to be read
  42. Returns:
  43. - res: An io.Reader for the given string
  44. */
  45. to_reader :: proc(r: ^Reader, s: string) -> (res: io.Reader) {
  46. reader_init(r, s)
  47. rr, _ := io.to_reader(reader_to_stream(r))
  48. return rr
  49. }
  50. /*
  51. Initializes a string Reader and returns an `io.Reader_At` for the given string
  52. Inputs:
  53. - r: A pointer to a Reader struct
  54. - s: The input string to be read
  55. Returns:
  56. - res: An `io.Reader_At` for the given string
  57. */
  58. to_reader_at :: proc(r: ^Reader, s: string) -> (res: io.Reader_At) {
  59. reader_init(r, s)
  60. rr, _ := io.to_reader_at(reader_to_stream(r))
  61. return rr
  62. }
  63. /*
  64. Returns the remaining length of the Reader
  65. Inputs:
  66. - r: A pointer to a Reader struct
  67. Returns:
  68. - res: The remaining length of the Reader
  69. */
  70. reader_length :: proc(r: ^Reader) -> (res: int) {
  71. if r.i >= i64(len(r.s)) {
  72. return 0
  73. }
  74. return int(i64(len(r.s)) - r.i)
  75. }
  76. /*
  77. Returns the length of the string stored in the Reader
  78. Inputs:
  79. - r: A pointer to a Reader struct
  80. Returns:
  81. - res: The length of the string stored in the Reader
  82. */
  83. reader_size :: proc(r: ^Reader) -> (res: i64) {
  84. return i64(len(r.s))
  85. }
  86. /*
  87. Reads len(p) bytes from the Reader's string and copies into the provided slice.
  88. Inputs:
  89. - r: A pointer to a Reader struct
  90. - p: A byte slice to copy data into
  91. Returns:
  92. - n: The number of bytes read
  93. - err: An `io.Error` if an error occurs while reading, including `.EOF`, otherwise `nil` denotes success.
  94. */
  95. reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) {
  96. if r.i >= i64(len(r.s)) {
  97. return 0, .EOF
  98. }
  99. r.prev_rune = -1
  100. n = copy(p, r.s[r.i:])
  101. r.i += i64(n)
  102. return
  103. }
  104. /*
  105. Reads len(p) bytes from the Reader's string and copies into the provided slice, at the specified offset from the current index.
  106. Inputs:
  107. - r: A pointer to a Reader struct
  108. - p: A byte slice to copy data into
  109. - off: The offset from which to read
  110. Returns:
  111. - n: The number of bytes read
  112. - err: An `io.Error` if an error occurs while reading, including `.EOF`, otherwise `nil` denotes success.
  113. */
  114. reader_read_at :: proc(r: ^Reader, p: []byte, off: i64) -> (n: int, err: io.Error) {
  115. if off < 0 {
  116. return 0, .Invalid_Offset
  117. }
  118. if off >= i64(len(r.s)) {
  119. return 0, .EOF
  120. }
  121. n = copy(p, r.s[off:])
  122. if n < len(p) {
  123. err = .EOF
  124. }
  125. return
  126. }
  127. /*
  128. Reads and returns a single byte from the Reader's string
  129. Inputs:
  130. - r: A pointer to a Reader struct
  131. Returns:
  132. - The byte read from the Reader
  133. - err: An `io.Error` if an error occurs while reading, including `.EOF`, otherwise `nil` denotes success.
  134. */
  135. reader_read_byte :: proc(r: ^Reader) -> (res: byte, err: io.Error) {
  136. r.prev_rune = -1
  137. if r.i >= i64(len(r.s)) {
  138. return 0, .EOF
  139. }
  140. b := r.s[r.i]
  141. r.i += 1
  142. return b, nil
  143. }
  144. /*
  145. Decrements the Reader's index (i) by 1
  146. Inputs:
  147. - r: A pointer to a Reader struct
  148. Returns:
  149. - err: An `io.Error` if `r.i <= 0` (`.Invalid_Unread`), otherwise `nil` denotes success.
  150. */
  151. reader_unread_byte :: proc(r: ^Reader) -> (err: io.Error) {
  152. if r.i <= 0 {
  153. return .Invalid_Unread
  154. }
  155. r.prev_rune = -1
  156. r.i -= 1
  157. return nil
  158. }
  159. /*
  160. Reads and returns a single rune and its `size` from the Reader's string
  161. Inputs:
  162. - r: A pointer to a Reader struct
  163. Returns:
  164. - rr: The rune read from the Reader
  165. - size: The size of the rune in bytes
  166. - err: An `io.Error` if an error occurs while reading
  167. */
  168. reader_read_rune :: proc(r: ^Reader) -> (rr: rune, size: int, err: io.Error) {
  169. if r.i >= i64(len(r.s)) {
  170. r.prev_rune = -1
  171. return 0, 0, .EOF
  172. }
  173. r.prev_rune = int(r.i)
  174. if c := r.s[r.i]; c < utf8.RUNE_SELF {
  175. r.i += 1
  176. return rune(c), 1, nil
  177. }
  178. rr, size = utf8.decode_rune_in_string(r.s[r.i:])
  179. r.i += i64(size)
  180. return
  181. }
  182. /*
  183. Decrements the Reader's index (i) by the size of the last read rune
  184. Inputs:
  185. - r: A pointer to a Reader struct
  186. WARNING: May only be used once and after a valid `read_rune` call
  187. Returns:
  188. - err: An `io.Error` if an error occurs while unreading (`.Invalid_Unread`), else `nil` denotes success.
  189. */
  190. reader_unread_rune :: proc(r: ^Reader) -> (err: io.Error) {
  191. if r.i <= 0 {
  192. return .Invalid_Unread
  193. }
  194. if r.prev_rune < 0 {
  195. return .Invalid_Unread
  196. }
  197. r.i = i64(r.prev_rune)
  198. r.prev_rune = -1
  199. return nil
  200. }
  201. /*
  202. Seeks the Reader's index to a new position
  203. Inputs:
  204. - r: A pointer to a Reader struct
  205. - offset: The new offset position
  206. - whence: The reference point for the new position (`.Start`, `.Current`, or `.End`)
  207. Returns:
  208. - The absolute offset after seeking
  209. - err: An `io.Error` if an error occurs while seeking (`.Invalid_Whence`, `.Invalid_Offset`)
  210. */
  211. reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (res: i64, err: io.Error) {
  212. r.prev_rune = -1
  213. abs: i64
  214. switch whence {
  215. case .Start:
  216. abs = offset
  217. case .Current:
  218. abs = r.i + offset
  219. case .End:
  220. abs = i64(len(r.s)) + offset
  221. case:
  222. return 0, .Invalid_Whence
  223. }
  224. if abs < 0 {
  225. return 0, .Invalid_Offset
  226. }
  227. r.i = abs
  228. return abs, nil
  229. }
  230. /*
  231. Writes the remaining content of the Reader's string into the provided `io.Writer`
  232. Inputs:
  233. - r: A pointer to a Reader struct
  234. - w: The io.Writer to write the remaining content into
  235. WARNING: Panics if writer writes more bytes than remainig length of string.
  236. Returns:
  237. - n: The number of bytes written
  238. - err: An io.Error if an error occurs while writing (`.Short_Write`)
  239. */
  240. reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
  241. r.prev_rune = -1
  242. if r.i >= i64(len(r.s)) {
  243. return 0, nil
  244. }
  245. s := r.s[r.i:]
  246. m: int
  247. m, err = io.write_string(w, s)
  248. if m > len(s) {
  249. panic("bytes.Reader.write_to: invalid io.write_string count")
  250. }
  251. r.i += i64(m)
  252. n = i64(m)
  253. if m != len(s) && err == nil {
  254. err = .Short_Write
  255. }
  256. return
  257. }
  258. /*
  259. VTable containing implementations for various `io.Stream` methods
  260. This VTable is used by the Reader struct to provide its functionality
  261. as an `io.Stream`.
  262. */
  263. @(private)
  264. _reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
  265. r := (^Reader)(stream_data)
  266. #partial switch mode {
  267. case .Size:
  268. n = reader_size(r)
  269. return
  270. case .Read:
  271. return io._i64_err(reader_read(r, p))
  272. case .Read_At:
  273. return io._i64_err(reader_read_at(r, p, offset))
  274. case .Seek:
  275. n, err = reader_seek(r, offset, whence)
  276. return
  277. case .Query:
  278. return io.query_utility({.Size, .Read, .Read_At, .Seek, .Query})
  279. }
  280. return 0, .Empty
  281. }