builder.odin 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package strings
  2. import "core:mem"
  3. import "core:unicode/utf8"
  4. import "core:strconv"
  5. Builder :: struct {
  6. buf: [dynamic]byte,
  7. }
  8. make_builder :: proc(allocator := context.allocator) -> Builder {
  9. return Builder{make([dynamic]byte, allocator)};
  10. }
  11. destroy_builder :: proc(b: ^Builder) {
  12. delete(b.buf);
  13. clear(&b.buf);
  14. }
  15. grow_builder :: proc(b: ^Builder, cap: int) {
  16. reserve(&b.buf, cap);
  17. }
  18. builder_from_slice :: proc(backing: []byte) -> Builder {
  19. s := transmute(mem.Raw_Slice)backing;
  20. d := mem.Raw_Dynamic_Array{
  21. data = s.data,
  22. len = 0,
  23. cap = s.len,
  24. allocator = mem.nil_allocator(),
  25. };
  26. return transmute(Builder)d;
  27. }
  28. to_string :: proc(b: Builder) -> string {
  29. return string(b.buf[:]);
  30. }
  31. builder_len :: proc(b: Builder) -> int {
  32. return len(b.buf);
  33. }
  34. builder_cap :: proc(b: Builder) -> int {
  35. return cap(b.buf);
  36. }
  37. write_byte :: proc(b: ^Builder, x: byte) {
  38. append(&b.buf, x);
  39. }
  40. write_rune :: proc(b: ^Builder, r: rune) -> int {
  41. if r < utf8.RUNE_SELF {
  42. write_byte(b, byte(r));
  43. return 1;
  44. }
  45. s, n := utf8.encode_rune(r);
  46. write_bytes(b, s[:n]);
  47. return n;
  48. }
  49. write_string :: proc(b: ^Builder, s: string) {
  50. write_bytes(b, cast([]byte)s);
  51. }
  52. write_bytes :: proc(b: ^Builder, x: []byte) {
  53. append(&b.buf, ..x);
  54. }
  55. @(private, static)
  56. DIGITS_LOWER := "0123456789abcdefx";
  57. write_quoted_string :: proc(b: ^Builder, s: string, quote: byte = '"') {
  58. write_byte(b, quote);
  59. for width := 0; len(s) > 0; s = s[width:] {
  60. r := rune(s[0]);
  61. width = 1;
  62. if r >= utf8.RUNE_SELF {
  63. r, width = utf8.decode_rune_in_string(s);
  64. }
  65. if width == 1 && r == utf8.RUNE_ERROR {
  66. write_byte(b, '\\');
  67. write_byte(b, 'x');
  68. write_byte(b, DIGITS_LOWER[s[0]>>4]);
  69. write_byte(b, DIGITS_LOWER[s[0]&0xf]);
  70. continue;
  71. }
  72. write_escaped_rune(b, r, quote);
  73. }
  74. write_byte(b, quote);
  75. }
  76. write_encoded_rune :: proc(b: ^Builder, r: rune, write_quote := true) {
  77. if write_quote do write_byte(b, '\'');
  78. switch r {
  79. case '\a': write_string(b, `\a"`);
  80. case '\b': write_string(b, `\b"`);
  81. case '\e': write_string(b, `\e"`);
  82. case '\f': write_string(b, `\f"`);
  83. case '\n': write_string(b, `\n"`);
  84. case '\r': write_string(b, `\r"`);
  85. case '\t': write_string(b, `\t"`);
  86. case '\v': write_string(b, `\v"`);
  87. case:
  88. if r < 32 {
  89. write_string(b, `\x`);
  90. buf: [2]byte;
  91. s := strconv.append_bits(buf[:], u64(r), 16, true, 64, strconv.digits, nil);
  92. switch len(s) {
  93. case 0: write_string(b, "00");
  94. case 1: write_byte(b, '0');
  95. case 2: write_string(b, s);
  96. }
  97. } else {
  98. write_rune(b, r);
  99. }
  100. }
  101. if write_quote do write_byte(b, '\'');
  102. }
  103. write_escaped_rune :: proc(b: ^Builder, r: rune, quote: byte, html_safe := false) {
  104. is_printable :: proc(r: rune) -> bool {
  105. if r <= 0xff {
  106. switch r {
  107. case 0x20..0x7e:
  108. return true;
  109. case 0xa1..0xff: // ¡ through ÿ except for the soft hyphen
  110. return r != 0xad; //
  111. }
  112. }
  113. // TODO(bill): A proper unicode library will be needed!
  114. return false;
  115. }
  116. if html_safe {
  117. switch r {
  118. case '<', '>', '&':
  119. write_byte(b, '\\');
  120. write_byte(b, 'u');
  121. for s := 12; s >= 0; s -= 4 {
  122. write_byte(b, DIGITS_LOWER[r>>uint(s) & 0xf]);
  123. }
  124. return;
  125. }
  126. }
  127. if r == rune(quote) || r == '\\' {
  128. write_byte(b, '\\');
  129. write_byte(b, byte(r));
  130. return;
  131. } else if is_printable(r) {
  132. write_encoded_rune(b, r, false);
  133. return;
  134. }
  135. switch r {
  136. case '\a': write_string(b, `\a`);
  137. case '\b': write_string(b, `\b`);
  138. case '\e': write_string(b, `\e`);
  139. case '\f': write_string(b, `\f`);
  140. case '\n': write_string(b, `\n`);
  141. case '\r': write_string(b, `\r`);
  142. case '\t': write_string(b, `\t`);
  143. case '\v': write_string(b, `\v`);
  144. case:
  145. switch {
  146. case r < ' ':
  147. write_byte(b, '\\');
  148. write_byte(b, 'x');
  149. write_byte(b, DIGITS_LOWER[byte(r)>>4]);
  150. write_byte(b, DIGITS_LOWER[byte(r)&0xf]);
  151. case r > utf8.MAX_RUNE:
  152. r = 0xfffd;
  153. fallthrough;
  154. case r < 0x10000:
  155. write_byte(b, '\\');
  156. write_byte(b, 'u');
  157. for s := 12; s >= 0; s -= 4 {
  158. write_byte(b, DIGITS_LOWER[r>>uint(s) & 0xf]);
  159. }
  160. case:
  161. write_byte(b, '\\');
  162. write_byte(b, 'U');
  163. for s := 28; s >= 0; s -= 4 {
  164. write_byte(b, DIGITS_LOWER[r>>uint(s) & 0xf]);
  165. }
  166. }
  167. }
  168. }
  169. write_u64 :: proc(b: ^Builder, i: u64, base: int = 10) {
  170. buf: [32]byte;
  171. s := strconv.append_bits(buf[:], u64(i), base, false, 64, strconv.digits, nil);
  172. write_string(b, s);
  173. }
  174. write_i64 :: proc(b: ^Builder, i: i64, base: int = 10) {
  175. buf: [32]byte;
  176. s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil);
  177. write_string(b, s);
  178. }
  179. write_uint :: proc(b: ^Builder, i: uint, base: int = 10) {
  180. write_u64(b, u64(i), base);
  181. }
  182. write_int :: proc(b: ^Builder, i: int, base: int = 10) {
  183. write_i64(b, i64(i), base);
  184. }