builder.odin 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. package strings
  2. import "core:runtime"
  3. import "core:unicode/utf8"
  4. import "core:strconv"
  5. import "core:io"
  6. /*
  7. Type definition for a procedure that flushes a Builder
  8. Inputs:
  9. - b: A pointer to the Builder
  10. Returns:
  11. A boolean indicating whether the Builder should be reset
  12. */
  13. Builder_Flush_Proc :: #type proc(b: ^Builder) -> (do_reset: bool)
  14. /*
  15. A dynamic byte buffer / string builder with helper procedures
  16. The dynamic array is wrapped inside the struct to be more opaque
  17. You can use `fmt.sbprint*` procedures with a `^strings.Builder` directly
  18. */
  19. Builder :: struct {
  20. buf: [dynamic]byte,
  21. }
  22. /*
  23. Produces a Builder with a default length of 0 and cap of 16
  24. *Allocates Using Provided Allocator*
  25. Inputs:
  26. - allocator: (default is context.allocator)
  27. Returns:
  28. A new Builder
  29. */
  30. builder_make_none :: proc(allocator := context.allocator) -> Builder {
  31. return Builder{buf=make([dynamic]byte, allocator)}
  32. }
  33. /*
  34. Produces a Builder with a specified length and cap of max(16,len) byte buffer
  35. *Allocates Using Provided Allocator*
  36. Inputs:
  37. - len: The desired length of the Builder's buffer
  38. - allocator: (default is context.allocator)
  39. Returns:
  40. A new Builder
  41. */
  42. builder_make_len :: proc(len: int, allocator := context.allocator) -> Builder {
  43. return Builder{buf=make([dynamic]byte, len, allocator)}
  44. }
  45. /*
  46. Produces a Builder with a specified length and cap
  47. *Allocates Using Provided Allocator*
  48. Inputs:
  49. - len: The desired length of the Builder's buffer
  50. - cap: The desired capacity of the Builder's buffer, cap is max(cap, len)
  51. - allocator: (default is context.allocator)
  52. Returns:
  53. A new Builder
  54. */
  55. builder_make_len_cap :: proc(len, cap: int, allocator := context.allocator) -> Builder {
  56. return Builder{buf=make([dynamic]byte, len, cap, allocator)}
  57. }
  58. // overload simple `builder_make_*` with or without len / cap parameters
  59. builder_make :: proc{
  60. builder_make_none,
  61. builder_make_len,
  62. builder_make_len_cap,
  63. }
  64. /*
  65. Initializes a Builder with a length of 0 and cap of 16
  66. It replaces the existing `buf`
  67. *Allocates Using Provided Allocator*
  68. Inputs:
  69. - b: A pointer to the Builder
  70. - allocator: (default is context.allocator)
  71. Returns:
  72. initialized ^Builder
  73. */
  74. builder_init_none :: proc(b: ^Builder, allocator := context.allocator) -> ^Builder {
  75. b.buf = make([dynamic]byte, allocator)
  76. return b
  77. }
  78. /*
  79. Initializes a Builder with a specified length and cap, which is max(len,16)
  80. It replaces the existing `buf`
  81. *Allocates Using Provided Allocator*
  82. Inputs:
  83. - b: A pointer to the Builder
  84. - len: The desired length of the Builder's buffer
  85. - allocator: (default is context.allocator)
  86. Returns:
  87. Initialized ^Builder
  88. */
  89. builder_init_len :: proc(b: ^Builder, len: int, allocator := context.allocator) -> ^Builder {
  90. b.buf = make([dynamic]byte, len, allocator)
  91. return b
  92. }
  93. /*
  94. Initializes a Builder with a specified length and cap
  95. It replaces the existing `buf`
  96. Inputs:
  97. - b: A pointer to the Builder
  98. - len: The desired length of the Builder's buffer
  99. - cap: The desired capacity of the Builder's buffer, actual max(len,cap)
  100. - allocator: (default is context.allocator)
  101. Returns:
  102. A pointer to the initialized Builder
  103. */
  104. builder_init_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator) -> ^Builder {
  105. b.buf = make([dynamic]byte, len, cap, allocator)
  106. return b
  107. }
  108. // Overload simple `builder_init_*` with or without len / ap parameters
  109. builder_init :: proc{
  110. builder_init_none,
  111. builder_init_len,
  112. builder_init_len_cap,
  113. }
  114. @(private)
  115. _builder_stream_vtable_obj := io.Stream_VTable{
  116. impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
  117. b := (^Builder)(s.stream_data)
  118. n = write_bytes(b, p)
  119. if n < len(p) {
  120. err = .EOF
  121. }
  122. return
  123. },
  124. impl_write_byte = proc(s: io.Stream, c: byte) -> (err: io.Error) {
  125. b := (^Builder)(s.stream_data)
  126. n := write_byte(b, c)
  127. if n == 0 {
  128. err = .EOF
  129. }
  130. return
  131. },
  132. impl_size = proc(s: io.Stream) -> i64 {
  133. b := (^Builder)(s.stream_data)
  134. return i64(len(b.buf))
  135. },
  136. impl_destroy = proc(s: io.Stream) -> io.Error {
  137. b := (^Builder)(s.stream_data)
  138. builder_destroy(b)
  139. return .None
  140. },
  141. }
  142. // NOTE(dweiler): Work around a miscompilation bug on Linux still.
  143. @(private)
  144. _builder_stream_vtable := &_builder_stream_vtable_obj
  145. /*
  146. Returns an io.Stream from a Builder
  147. Inputs:
  148. - b: A pointer to the Builder
  149. Returns:
  150. An io.Stream
  151. */
  152. to_stream :: proc(b: ^Builder) -> io.Stream {
  153. return io.Stream{stream_vtable=_builder_stream_vtable, stream_data=b}
  154. }
  155. /*
  156. Returns an io.Writer from a Builder
  157. Inputs:
  158. - b: A pointer to the Builder
  159. Returns:
  160. An io.Writer
  161. */
  162. to_writer :: proc(b: ^Builder) -> io.Writer {
  163. return io.to_writer(to_stream(b))
  164. }
  165. /*
  166. Deletes the Builder byte buffer content
  167. Inputs:
  168. - b: A pointer to the Builder
  169. */
  170. builder_destroy :: proc(b: ^Builder) {
  171. delete(b.buf)
  172. b.buf = nil
  173. }
  174. /*
  175. Reserves the Builder byte buffer to a specific capacity, when it's higher than before
  176. Inputs:
  177. - b: A pointer to the Builder
  178. - cap: The desired capacity for the Builder's buffer
  179. */
  180. builder_grow :: proc(b: ^Builder, cap: int) {
  181. reserve(&b.buf, cap)
  182. }
  183. /*
  184. Clears the Builder byte buffer content (sets len to zero)
  185. Inputs:
  186. - b: A pointer to the Builder
  187. */
  188. builder_reset :: proc(b: ^Builder) {
  189. clear(&b.buf)
  190. }
  191. /*
  192. Creates a Builder from a slice of bytes with the same slice length as its capacity. Used in fmt.bprint*
  193. *Uses Nil Allocator - Does NOT allocate*
  194. Inputs:
  195. - backing: A slice of bytes to be used as the backing buffer
  196. Returns:
  197. A new Builder
  198. Example:
  199. import "core:fmt"
  200. import "core:strings"
  201. builder_from_bytes_example :: proc() {
  202. bytes: [8]byte // <-- gets filled
  203. builder := strings.builder_from_bytes(bytes[:])
  204. strings.write_byte(&builder, 'a')
  205. fmt.println(strings.to_string(builder)) // -> "a"
  206. strings.write_byte(&builder, 'b')
  207. fmt.println(strings.to_string(builder)) // -> "ab"
  208. }
  209. Output:
  210. a
  211. ab
  212. */
  213. builder_from_bytes :: proc(backing: []byte) -> Builder {
  214. s := transmute(runtime.Raw_Slice)backing
  215. d := runtime.Raw_Dynamic_Array{
  216. data = s.data,
  217. len = 0,
  218. cap = s.len,
  219. allocator = runtime.nil_allocator(),
  220. }
  221. return Builder{
  222. buf = transmute([dynamic]byte)d,
  223. }
  224. }
  225. // Alias to `builder_from_bytes`
  226. builder_from_slice :: builder_from_bytes
  227. /*
  228. Casts the Builder byte buffer to a string and returns it
  229. Inputs:
  230. - b: A Builder
  231. Returns:
  232. The contents of the Builder's buffer, as a string
  233. */
  234. to_string :: proc(b: Builder) -> string {
  235. return string(b.buf[:])
  236. }
  237. /*
  238. Returns the length of the Builder's buffer, in bytes
  239. Inputs:
  240. - b: A Builder
  241. Returns:
  242. The length of the Builder's buffer
  243. */
  244. builder_len :: proc(b: Builder) -> int {
  245. return len(b.buf)
  246. }
  247. /*
  248. Returns the capacity of the Builder's buffer, in bytes
  249. Inputs:
  250. - b: A Builder
  251. Returns:
  252. The capacity of the Builder's buffer
  253. */
  254. builder_cap :: proc(b: Builder) -> int {
  255. return cap(b.buf)
  256. }
  257. /*
  258. The free space left in the Builder's buffer, in bytes
  259. Inputs:
  260. - b: A Builder
  261. Returns:
  262. The available space left in the Builder's buffer
  263. */
  264. builder_space :: proc(b: Builder) -> int {
  265. return cap(b.buf) - len(b.buf)
  266. }
  267. /*
  268. Appends a byte to the Builder and returns the number of bytes appended
  269. Inputs:
  270. - b: A pointer to the Builder
  271. - x: The byte to be appended
  272. Returns:
  273. The number of bytes appended
  274. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  275. Example:
  276. import "core:fmt"
  277. import "core:strings"
  278. write_byte_example :: proc() {
  279. builder := strings.builder_make()
  280. strings.write_byte(&builder, 'a') // 1
  281. strings.write_byte(&builder, 'b') // 1
  282. fmt.println(strings.to_string(builder)) // -> ab
  283. }
  284. Output:
  285. ab
  286. */
  287. write_byte :: proc(b: ^Builder, x: byte) -> (n: int) {
  288. n0 := len(b.buf)
  289. append(&b.buf, x)
  290. n1 := len(b.buf)
  291. return n1-n0
  292. }
  293. /*
  294. Appends a slice of bytes to the Builder and returns the number of bytes appended
  295. Inputs:
  296. - b: A pointer to the Builder
  297. - x: The slice of bytes to be appended
  298. Example:
  299. import "core:fmt"
  300. import "core:strings"
  301. write_bytes_example :: proc() {
  302. builder := strings.builder_make()
  303. bytes := [?]byte { 'a', 'b', 'c' }
  304. strings.write_bytes(&builder, bytes[:]) // 3
  305. fmt.println(strings.to_string(builder)) // -> abc
  306. }
  307. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  308. Returns:
  309. The number of bytes appended
  310. */
  311. write_bytes :: proc(b: ^Builder, x: []byte) -> (n: int) {
  312. n0 := len(b.buf)
  313. append(&b.buf, ..x)
  314. n1 := len(b.buf)
  315. return n1-n0
  316. }
  317. /*
  318. Appends a single rune to the Builder and returns the number of bytes written and an `io.Error`
  319. Inputs:
  320. - b: A pointer to the Builder
  321. - r: The rune to be appended
  322. Returns:
  323. The number of bytes written and an io.Error (if any)
  324. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  325. Example:
  326. import "core:fmt"
  327. import "core:strings"
  328. write_rune_example :: proc() {
  329. builder := strings.builder_make()
  330. strings.write_rune(&builder, 'ä') // 2 None
  331. strings.write_rune(&builder, 'b') // 1 None
  332. fmt.println(strings.to_string(builder)) // -> äb
  333. }
  334. Output:
  335. äb
  336. */
  337. write_rune :: proc(b: ^Builder, r: rune) -> (int, io.Error) {
  338. return io.write_rune(to_writer(b), r)
  339. }
  340. /*
  341. Appends a quoted rune to the Builder and returns the number of bytes written
  342. Inputs:
  343. - b: A pointer to the Builder
  344. - r: The rune to be appended
  345. Returns:
  346. The number of bytes written
  347. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  348. Example:
  349. import "core:fmt"
  350. import "core:strings"
  351. write_quoted_rune_example :: proc() {
  352. builder := strings.builder_make()
  353. strings.write_string(&builder, "abc") // 3
  354. strings.write_quoted_rune(&builder, 'ä') // 4
  355. strings.write_string(&builder, "abc") // 3
  356. fmt.println(strings.to_string(builder)) // -> abc'ä'abc
  357. }
  358. Output:
  359. abc'ä'abc
  360. */
  361. write_quoted_rune :: proc(b: ^Builder, r: rune) -> (n: int) {
  362. return io.write_quoted_rune(to_writer(b), r)
  363. }
  364. /*
  365. Appends a string to the Builder and returns the number of bytes written
  366. Inputs:
  367. - b: A pointer to the Builder
  368. - s: The string to be appended
  369. Returns:
  370. The number of bytes written
  371. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  372. Example:
  373. import "core:fmt"
  374. import "core:strings"
  375. write_string_example :: proc() {
  376. builder := strings.builder_make()
  377. strings.write_string(&builder, "a") // 1
  378. strings.write_string(&builder, "bc") // 2
  379. fmt.println(strings.to_string(builder)) // -> abc
  380. }
  381. Output:
  382. abc
  383. */
  384. write_string :: proc(b: ^Builder, s: string) -> (n: int) {
  385. n0 := len(b.buf)
  386. append(&b.buf, s)
  387. n1 := len(b.buf)
  388. return n1-n0
  389. }
  390. /*
  391. Pops and returns the last byte in the Builder or 0 when the Builder is empty
  392. Inputs:
  393. - b: A pointer to the Builder
  394. Returns:
  395. The last byte in the Builder or 0 if empty
  396. */
  397. pop_byte :: proc(b: ^Builder) -> (r: byte) {
  398. if len(b.buf) == 0 {
  399. return 0
  400. }
  401. r = b.buf[len(b.buf)-1]
  402. d := cast(^runtime.Raw_Dynamic_Array)&b.buf
  403. d.len = max(d.len-1, 0)
  404. return
  405. }
  406. /*
  407. Pops the last rune in the Builder and returns the popped rune and its rune width or (0, 0) if empty
  408. Inputs:
  409. - b: A pointer to the Builder
  410. Returns:
  411. The popped rune and its rune width or (0, 0) if empty
  412. */
  413. pop_rune :: proc(b: ^Builder) -> (r: rune, width: int) {
  414. if len(b.buf) == 0 {
  415. return 0, 0
  416. }
  417. r, width = utf8.decode_last_rune(b.buf[:])
  418. d := cast(^runtime.Raw_Dynamic_Array)&b.buf
  419. d.len = max(d.len-width, 0)
  420. return
  421. }
  422. @(private)
  423. DIGITS_LOWER := "0123456789abcdefx"
  424. /*
  425. Inputs:
  426. - b: A pointer to the Builder
  427. - str: The string to be quoted and appended
  428. - quote: The optional quote character (default is double quotes)
  429. Returns:
  430. The number of bytes written
  431. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  432. Example:
  433. import "core:fmt"
  434. import "core:strings"
  435. write_quoted_string_example :: proc() {
  436. builder := strings.builder_make()
  437. strings.write_quoted_string(&builder, "a") // 3
  438. strings.write_quoted_string(&builder, "bc", '\'') // 4
  439. strings.write_quoted_string(&builder, "xyz") // 5
  440. fmt.println(strings.to_string(builder))
  441. }
  442. Output:
  443. "a"'bc'"xyz"
  444. */
  445. write_quoted_string :: proc(b: ^Builder, str: string, quote: byte = '"') -> (n: int) {
  446. n, _ = io.write_quoted_string(to_writer(b), str, quote)
  447. return
  448. }
  449. /*
  450. Appends a rune to the Builder and returns the number of bytes written
  451. Inputs:
  452. - b: A pointer to the Builder
  453. - r: The rune to be appended
  454. - write_quote: Optional boolean flag to wrap in single-quotes (') (default is true)
  455. Returns:
  456. The number of bytes written
  457. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  458. Example:
  459. import "core:fmt"
  460. import "core:strings"
  461. write_encoded_rune_example :: proc() {
  462. builder := strings.builder_make()
  463. strings.write_encoded_rune(&builder, 'a', false) // 1
  464. strings.write_encoded_rune(&builder, '\"', true) // 3
  465. strings.write_encoded_rune(&builder, 'x', false) // 1
  466. fmt.println(strings.to_string(builder))
  467. }
  468. Output:
  469. a'"'x
  470. */
  471. write_encoded_rune :: proc(b: ^Builder, r: rune, write_quote := true) -> (n: int) {
  472. n, _ = io.write_encoded_rune(to_writer(b), r, write_quote)
  473. return
  474. }
  475. /*
  476. Appends an escaped rune to the Builder and returns the number of bytes written
  477. Inputs:
  478. - b: A pointer to the Builder
  479. - r: The rune to be appended
  480. - quote: The quote character
  481. - html_safe: Optional boolean flag to encode '<', '>', '&' as digits (default is false)
  482. **Usage**
  483. - '\a' will be written as such
  484. - `r` and `quote` match and `quote` is `\\` - they will be written as two slashes
  485. - `html_safe` flag in case the runes '<', '>', '&' should be encoded as digits e.g. `\u0026`
  486. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  487. Returns:
  488. The number of bytes written
  489. */
  490. write_escaped_rune :: proc(b: ^Builder, r: rune, quote: byte, html_safe := false) -> (n: int) {
  491. n, _ = io.write_escaped_rune(to_writer(b), r, quote, html_safe)
  492. return
  493. }
  494. /*
  495. Writes a f64 value to the Builder and returns the number of characters written
  496. Inputs:
  497. - b: A pointer to the Builder
  498. - f: The f64 value to be appended
  499. - fmt: The format byte
  500. - prec: The precision
  501. - bit_size: The bit size
  502. - always_signed: Optional boolean flag to always include the sign (default is false)
  503. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  504. Returns:
  505. The number of characters written
  506. */
  507. write_float :: proc(b: ^Builder, f: f64, fmt: byte, prec, bit_size: int, always_signed := false) -> (n: int) {
  508. buf: [384]byte
  509. s := strconv.append_float(buf[:], f, fmt, prec, bit_size)
  510. // If the result starts with a `+` then unless we always want signed results,
  511. // we skip it unless it's followed by an `I` (because of +Inf).
  512. if !always_signed && (buf[0] == '+' && buf[1] != 'I') {
  513. s = s[1:]
  514. }
  515. return write_string(b, s)
  516. }
  517. /*
  518. Writes a f16 value to the Builder and returns the number of characters written
  519. Inputs:
  520. - b: A pointer to the Builder
  521. - f: The f16 value to be appended
  522. - fmt: The format byte
  523. - always_signed: Optional boolean flag to always include the sign
  524. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  525. Returns:
  526. The number of characters written
  527. */
  528. write_f16 :: proc(b: ^Builder, f: f16, fmt: byte, always_signed := false) -> (n: int) {
  529. buf: [384]byte
  530. s := strconv.append_float(buf[:], f64(f), fmt, 2*size_of(f), 8*size_of(f))
  531. if !always_signed && (buf[0] == '+' && buf[1] != 'I') {
  532. s = s[1:]
  533. }
  534. return write_string(b, s)
  535. }
  536. /*
  537. Writes a f32 value to the Builder and returns the number of characters written
  538. Inputs:
  539. - b: A pointer to the Builder
  540. - f: The f32 value to be appended
  541. - fmt: The format byte
  542. - always_signed: Optional boolean flag to always include the sign
  543. Returns:
  544. The number of characters written
  545. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  546. Example:
  547. import "core:fmt"
  548. import "core:strings"
  549. write_f32_example :: proc() {
  550. builder := strings.builder_make()
  551. strings.write_f32(&builder, 3.14159, 'f') // 6
  552. strings.write_string(&builder, " - ") // 3
  553. strings.write_f32(&builder, -0.123, 'e') // 8
  554. fmt.println(strings.to_string(builder)) // -> 3.14159012 - -1.23000003e-01
  555. }
  556. Output:
  557. 3.14159012 - -1.23000003e-01
  558. */
  559. write_f32 :: proc(b: ^Builder, f: f32, fmt: byte, always_signed := false) -> (n: int) {
  560. buf: [384]byte
  561. s := strconv.append_float(buf[:], f64(f), fmt, 2*size_of(f), 8*size_of(f))
  562. if !always_signed && (buf[0] == '+' && buf[1] != 'I') {
  563. s = s[1:]
  564. }
  565. return write_string(b, s)
  566. }
  567. /*
  568. Writes a f32 value to the Builder and returns the number of characters written
  569. Inputs:
  570. - b: A pointer to the Builder
  571. - f: The f32 value to be appended
  572. - fmt: The format byte
  573. - always_signed: Optional boolean flag to always include the sign
  574. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  575. Returns:
  576. The number of characters written
  577. */
  578. write_f64 :: proc(b: ^Builder, f: f64, fmt: byte, always_signed := false) -> (n: int) {
  579. buf: [384]byte
  580. s := strconv.append_float(buf[:], f64(f), fmt, 2*size_of(f), 8*size_of(f))
  581. if !always_signed && (buf[0] == '+' && buf[1] != 'I') {
  582. s = s[1:]
  583. }
  584. return write_string(b, s)
  585. }
  586. /*
  587. Writes a u64 value to the Builder and returns the number of characters written
  588. Inputs:
  589. - b: A pointer to the Builder
  590. - i: The u64 value to be appended
  591. - base: The optional base for the numeric representation
  592. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  593. Returns:
  594. The number of characters written
  595. */
  596. write_u64 :: proc(b: ^Builder, i: u64, base: int = 10) -> (n: int) {
  597. buf: [32]byte
  598. s := strconv.append_bits(buf[:], i, base, false, 64, strconv.digits, nil)
  599. return write_string(b, s)
  600. }
  601. /*
  602. Writes a i64 value to the Builder and returns the number of characters written
  603. Inputs:
  604. - b: A pointer to the Builder
  605. - i: The i64 value to be appended
  606. - base: The optional base for the numeric representation
  607. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  608. Returns:
  609. The number of characters written
  610. */
  611. write_i64 :: proc(b: ^Builder, i: i64, base: int = 10) -> (n: int) {
  612. buf: [32]byte
  613. s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil)
  614. return write_string(b, s)
  615. }
  616. /*
  617. Writes a uint value to the Builder and returns the number of characters written
  618. Inputs:
  619. - b: A pointer to the Builder
  620. - i: The uint value to be appended
  621. - base: The optional base for the numeric representation
  622. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  623. Returns:
  624. The number of characters written
  625. */
  626. write_uint :: proc(b: ^Builder, i: uint, base: int = 10) -> (n: int) {
  627. return write_u64(b, u64(i), base)
  628. }
  629. /*
  630. Writes a int value to the Builder and returns the number of characters written
  631. Inputs:
  632. - b: A pointer to the Builder
  633. - i: The int value to be appended
  634. - base: The optional base for the numeric representation
  635. NOTE: The backing dynamic array may be fixed in capacity or fail to resize, `n` states the number actually written.
  636. Returns:
  637. The number of characters written
  638. */
  639. write_int :: proc(b: ^Builder, i: int, base: int = 10) -> (n: int) {
  640. return write_i64(b, i64(i), base)
  641. }