diff options
| author | gingerBill <bill@gingerbill.org> | 2019-01-06 22:11:45 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2019-01-06 22:11:45 +0000 |
| commit | 64f84ef9a32b4e24374adc91abffa0104778be1e (patch) | |
| tree | d48d44ca03e319c9023808d5a1aaa2291461511e /core/strings | |
| parent | d1b9f3ac74df5533f1857a26831419aeb560fd2f (diff) | |
fmt.printf("%q", str); (quotes strings)
Diffstat (limited to 'core/strings')
| -rw-r--r-- | core/strings/builder.odin | 88 |
1 files changed, 75 insertions, 13 deletions
diff --git a/core/strings/builder.odin b/core/strings/builder.odin index c79352719..389030ba4 100644 --- a/core/strings/builder.odin +++ b/core/strings/builder.odin @@ -62,25 +62,25 @@ write_bytes :: proc(b: ^Builder, x: []byte) { } -write_encoded_rune :: proc(b: ^Builder, r: rune) { - write_byte(b, '\''); +write_encoded_rune :: proc(b: ^Builder, r: rune, write_quote := true) { + if write_quote do write_byte(b, '\''); switch r { - case '\a': write_string(b, "\\a"); - case '\b': write_string(b, "\\b"); - case '\e': write_string(b, "\\e"); - case '\f': write_string(b, "\\f"); - case '\n': write_string(b, "\\n"); - case '\r': write_string(b, "\\r"); - case '\t': write_string(b, "\\t"); - case '\v': write_string(b, "\\v"); + case '\a': write_string(b, `\a"`); + case '\b': write_string(b, `\b"`); + case '\e': write_string(b, `\e"`); + case '\f': write_string(b, `\f"`); + case '\n': write_string(b, `\n"`); + case '\r': write_string(b, `\r"`); + case '\t': write_string(b, `\t"`); + case '\v': write_string(b, `\v"`); case: if r < 32 { - write_string(b, "\\x"); + write_string(b, `\x`); buf: [2]byte; s := strconv.append_bits(buf[:], u64(r), 16, true, 64, strconv.digits, nil); switch len(s) { case 0: write_string(b, "00"); - case 1: write_rune(b, '0'); + case 1: write_byte(b, '0'); case 2: write_string(b, s); } } else { @@ -88,7 +88,69 @@ write_encoded_rune :: proc(b: ^Builder, r: rune) { } } - write_byte(b, '\''); + if write_quote do write_byte(b, '\''); +} + + +write_escaped_rune :: proc(b: ^Builder, r: rune, quote: byte) { + static DIGITS_LOWER := "0123456789abcdefx"; + + is_printable :: proc(r: rune) -> bool { + if r <= 0xff { + switch r { + case 0x20..0x7e: + return true; + case 0xa1..0xff: // ¡ through ÿ except for the soft hyphen + return r != 0xad; // + } + } + + // TODO(bill): A proper unicode library will be needed! + return false; + } + + if r == rune(quote) || r == '\\' { + write_byte(b, '\\'); + write_byte(b, byte(r)); + return; + } else if is_printable(r) { + write_encoded_rune(b, r, false); + return; + } + switch r { + case '\a': write_string(b, `\a`); + case '\b': write_string(b, `\b`); + case '\e': write_string(b, `\e`); + case '\f': write_string(b, `\f`); + case '\n': write_string(b, `\n`); + case '\r': write_string(b, `\r`); + case '\t': write_string(b, `\t`); + case '\v': write_string(b, `\v`); + case: + switch { + case r < ' ': + write_byte(b, '\\'); + write_byte(b, 'x'); + write_byte(b, DIGITS_LOWER[byte(r)>>4]); + write_byte(b, DIGITS_LOWER[byte(r)&0xf]); + + case r > utf8.MAX_RUNE: + r = 0xfffd; + fallthrough; + case r < 0x10000: + write_byte(b, '\\'); + write_byte(b, 'u'); + for s := 12; s >= 0; s -= 4 { + write_byte(b, DIGITS_LOWER[r>>uint(s) & 0xf]); + } + case: + write_byte(b, '\\'); + write_byte(b, 'U'); + for s := 28; s >= 0; s -= 4 { + write_byte(b, DIGITS_LOWER[r>>uint(s) & 0xf]); + } + } + } } |