mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-30 19:30:06 +00:00
Add string16 and cstring16 (UTF-16 based strings)
This commit is contained in:
@@ -1551,6 +1551,79 @@ fmt_string :: proc(fi: ^Info, s: string, verb: rune) {
|
||||
fmt_cstring :: proc(fi: ^Info, s: cstring, verb: rune) {
|
||||
fmt_string(fi, string(s), verb)
|
||||
}
|
||||
|
||||
// Formats a string UTF-16 with a specific format.
|
||||
//
|
||||
// Inputs:
|
||||
// - fi: Pointer to the Info struct containing format settings.
|
||||
// - s: The string to format.
|
||||
// - verb: The format specifier character (e.g. 's', 'v', 'q', 'x', 'X').
|
||||
//
|
||||
fmt_string16 :: proc(fi: ^Info, s: string16, verb: rune) {
|
||||
s, verb := s, verb
|
||||
if ol, ok := fi.optional_len.?; ok {
|
||||
s = s[:clamp(ol, 0, len(s))]
|
||||
}
|
||||
if !fi.in_bad && fi.record_level > 0 && verb == 'v' {
|
||||
verb = 'q'
|
||||
}
|
||||
|
||||
switch verb {
|
||||
case 's', 'v':
|
||||
if fi.width_set {
|
||||
if fi.width > len(s) {
|
||||
if fi.minus {
|
||||
io.write_string16(fi.writer, s, &fi.n)
|
||||
}
|
||||
|
||||
for _ in 0..<fi.width - len(s) {
|
||||
io.write_byte(fi.writer, ' ', &fi.n)
|
||||
}
|
||||
|
||||
if !fi.minus {
|
||||
io.write_string16(fi.writer, s, &fi.n)
|
||||
}
|
||||
} else {
|
||||
io.write_string16(fi.writer, s, &fi.n)
|
||||
}
|
||||
} else {
|
||||
io.write_string16(fi.writer, s, &fi.n)
|
||||
}
|
||||
|
||||
case 'q', 'w': // quoted string
|
||||
io.write_quoted_string16(fi.writer, s, '"', &fi.n)
|
||||
|
||||
case 'x', 'X':
|
||||
space := fi.space
|
||||
fi.space = false
|
||||
defer fi.space = space
|
||||
|
||||
for i in 0..<len(s) {
|
||||
if i > 0 && space {
|
||||
io.write_byte(fi.writer, ' ', &fi.n)
|
||||
}
|
||||
char_set := __DIGITS_UPPER
|
||||
if verb == 'x' {
|
||||
char_set = __DIGITS_LOWER
|
||||
}
|
||||
_fmt_int(fi, u64(s[i]), 16, false, bit_size=16, digits=char_set)
|
||||
}
|
||||
|
||||
case:
|
||||
fmt_bad_verb(fi, verb)
|
||||
}
|
||||
}
|
||||
// Formats a C-style UTF-16 string with a specific format.
|
||||
//
|
||||
// Inputs:
|
||||
// - fi: Pointer to the Info struct containing format settings.
|
||||
// - s: The C-style string to format.
|
||||
// - verb: The format specifier character (Ref fmt_string).
|
||||
//
|
||||
fmt_cstring16 :: proc(fi: ^Info, s: cstring16, verb: rune) {
|
||||
fmt_string16(fi, string16(s), verb)
|
||||
}
|
||||
|
||||
// Formats a raw pointer with a specific format.
|
||||
//
|
||||
// Inputs:
|
||||
@@ -3210,6 +3283,9 @@ fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) {
|
||||
case string: fmt_string(fi, a, verb)
|
||||
case cstring: fmt_cstring(fi, a, verb)
|
||||
|
||||
case string16: fmt_string16(fi, a, verb)
|
||||
case cstring16: fmt_cstring16(fi, a, verb)
|
||||
|
||||
case typeid: reflect.write_typeid(fi.writer, a, &fi.n)
|
||||
|
||||
case i16le: fmt_int(fi, u64(a), true, 16, verb)
|
||||
|
||||
@@ -5,6 +5,7 @@ package io
|
||||
|
||||
import "base:intrinsics"
|
||||
import "core:unicode/utf8"
|
||||
import "core:unicode/utf16"
|
||||
|
||||
// Seek whence values
|
||||
Seek_From :: enum {
|
||||
@@ -314,6 +315,29 @@ write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int,
|
||||
return write(s, transmute([]byte)str, n_written)
|
||||
}
|
||||
|
||||
// write_string16 writes the contents of the string16 s to w reencoded as utf-8
|
||||
write_string16 :: proc(s: Writer, str: string16, n_written: ^int = nil) -> (n: int, err: Error) {
|
||||
for i := 0; i < len(str); i += 1 {
|
||||
r := rune(utf16.REPLACEMENT_CHAR)
|
||||
|
||||
switch c := str[i]; {
|
||||
case c < utf16._surr1, utf16._surr3 <= c:
|
||||
r = rune(c)
|
||||
case utf16._surr1 <= c && c < utf16._surr2 && i+1 < len(str) &&
|
||||
utf16._surr2 <= str[i+1] && str[i+1] < utf16._surr3:
|
||||
r = utf16.decode_surrogate_pair(rune(c), rune(str[i+1]))
|
||||
i += 1
|
||||
}
|
||||
|
||||
w, err := write_rune(s, r, n_written)
|
||||
n += w
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// write_rune writes a UTF-8 encoded rune to w.
|
||||
write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err: Error) {
|
||||
defer if err == nil && n_written != nil {
|
||||
|
||||
@@ -264,6 +264,33 @@ write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written
|
||||
return
|
||||
}
|
||||
|
||||
write_quoted_string16 :: proc(w: Writer, str: string16, quote: byte = '"', n_written: ^int = nil, for_json := false) -> (n: int, err: Error) {
|
||||
defer if n_written != nil {
|
||||
n_written^ += n
|
||||
}
|
||||
write_byte(w, quote, &n) or_return
|
||||
for width, s := 0, str; len(s) > 0; s = s[width:] {
|
||||
r := rune(s[0])
|
||||
width = 1
|
||||
if r >= utf8.RUNE_SELF {
|
||||
r, width = utf16.decode_rune_in_string(s)
|
||||
}
|
||||
if width == 1 && r == utf8.RUNE_ERROR {
|
||||
write_byte(w, '\\', &n) or_return
|
||||
write_byte(w, 'x', &n) or_return
|
||||
write_byte(w, DIGITS_LOWER[s[0]>>4], &n) or_return
|
||||
write_byte(w, DIGITS_LOWER[s[0]&0xf], &n) or_return
|
||||
continue
|
||||
}
|
||||
|
||||
n_wrapper(write_escaped_rune(w, r, quote, false, nil, for_json), &n) or_return
|
||||
|
||||
}
|
||||
write_byte(w, quote, &n) or_return
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// writer append a quoted rune into the byte buffer, return the written size
|
||||
write_quoted_rune :: proc(w: Writer, r: rune) -> (n: int) {
|
||||
_write_byte :: #force_inline proc(w: Writer, c: byte) -> int {
|
||||
|
||||
@@ -106,6 +106,26 @@ decode :: proc(d: []rune, s: []u16) -> (n: int) {
|
||||
return
|
||||
}
|
||||
|
||||
decode_rune_in_string :: proc(s: string16) -> (r: rune, width: int) {
|
||||
r = rune(REPLACEMENT_CHAR)
|
||||
n := len(s)
|
||||
if n < 1 {
|
||||
return
|
||||
}
|
||||
width = 1
|
||||
|
||||
|
||||
switch c := s[0]; {
|
||||
case c < _surr1, _surr3 <= c:
|
||||
r = rune(c)
|
||||
case _surr1 <= c && c < _surr2 && 1 < len(s) &&
|
||||
_surr2 <= s[1] && s[1] < _surr3:
|
||||
r = decode_surrogate_pair(rune(c), rune(s[1]))
|
||||
width += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
rune_count :: proc(s: []u16) -> (n: int) {
|
||||
for i := 0; i < len(s); i += 1 {
|
||||
c := s[i]
|
||||
|
||||
Reference in New Issue
Block a user