diff --git a/core/_preload.odin b/core/_preload.odin index 83ce45ce7..953d38c43 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -460,11 +460,7 @@ __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int, return slice.count; } - - ok := true; - if item_count > (slice.capacity-slice.count) { - item_count = (slice.capacity-slice.count); - } + item_count = min(slice.capacity-slice.count, item_count); if item_count > 0 { data := cast(^byte)slice.data; assert(data != nil); diff --git a/core/fmt.odin b/core/fmt.odin index eb9233996..eb2353b72 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -7,37 +7,20 @@ _BUFFER_SIZE :: 1<<12; -Buffer :: struct { - data: []byte, - length: int, +write_string :: proc(buf: ^[]byte, s: string) { + append(buf^, ..cast([]byte)s); } - -buffer_write :: proc(buf: ^Buffer, b: []byte) { - if buf.length < buf.data.count { - n := min(buf.data.count-buf.length, b.count); - if n > 0 { - copy(buf.data[buf.length..], b[..n]); - buf.length += n; - } - } +write_byte :: proc(buf: ^[]byte, b: byte) { + append(buf^, b); } -buffer_write_string :: proc(buf: ^Buffer, s: string) { - buffer_write(buf, cast([]byte)s); -} -buffer_write_byte :: proc(buf: ^Buffer, b: byte) { - if buf.length < buf.data.count { - buf.data[buf.length] = b; - buf.length++; - } -} -buffer_write_rune :: proc(buf: ^Buffer, r: rune) { +write_rune :: proc(buf: ^[]byte, r: rune) { if r < utf8.RUNE_SELF { - buffer_write_byte(buf, cast(byte)r); + write_byte(buf, cast(byte)r); return; } b, n := utf8.encode_rune(r); - buffer_write(buf, b[..n]); + append(buf^, ..b[..n]); } Fmt_Info :: struct { @@ -55,7 +38,7 @@ Fmt_Info :: struct { reordered: bool, good_arg_index: bool, - buf: ^Buffer, + buf: ^[]byte, arg: any, // Temporary } @@ -63,25 +46,25 @@ Fmt_Info :: struct { fprint :: proc(fd: os.Handle, args: ..any) -> int { data: [_BUFFER_SIZE]byte; - buf := Buffer{data[..], 0}; + buf := data[..0]; bprint(^buf, ..args); - os.write(fd, buf.data[..buf.length]); - return buf.length; + os.write(fd, buf[..buf.count]); + return buf.count; } fprintln :: proc(fd: os.Handle, args: ..any) -> int { data: [_BUFFER_SIZE]byte; - buf := Buffer{data[..], 0}; + buf := data[..0]; bprintln(^buf, ..args); - os.write(fd, buf.data[..buf.length]); - return buf.length; + os.write(fd, buf[..buf.count]); + return buf.count; } fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int { data: [_BUFFER_SIZE]byte; - buf := Buffer{data[..], 0}; + buf := data[..0]; bprintf(^buf, fmt, ..args); - os.write(fd, buf.data[..buf.length]); - return buf.length; + os.write(fd, buf[..buf.count]); + return buf.count; } @@ -98,12 +81,12 @@ printf :: proc(fmt: string, args: ..any) -> int { fprint_type :: proc(fd: os.Handle, info: ^Type_Info) { data: [_BUFFER_SIZE]byte; - buf := Buffer{data[..], 0}; - buffer_write_type(^buf, info); - os.write(fd, buf.data[..buf.length]); + buf := data[..0]; + write_type(^buf, info); + os.write(fd, buf[..buf.count]); } -buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { +write_type :: proc(buf: ^[]byte, ti: ^Type_Info) { if ti == nil { return; } @@ -111,131 +94,131 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { using Type_Info; match info in ti { case Named: - buffer_write_string(buf, info.name); + write_string(buf, info.name); case Integer: match { - case ti == type_info(int): buffer_write_string(buf, "int"); - case ti == type_info(uint): buffer_write_string(buf, "uint"); + case ti == type_info(int): write_string(buf, "int"); + case ti == type_info(uint): write_string(buf, "uint"); default: - buffer_write_string(buf, info.signed ? "i" : "u"); + write_string(buf, info.signed ? "i" : "u"); fi := Fmt_Info{buf = buf}; fmt_int(^fi, cast(u64)(8*info.size), false, 'd'); } case Float: match info.size { - case 4: buffer_write_string(buf, "f32"); - case 8: buffer_write_string(buf, "f64"); + case 4: write_string(buf, "f32"); + case 8: write_string(buf, "f64"); } - case String: buffer_write_string(buf, "string"); - case Boolean: buffer_write_string(buf, "bool"); + case String: write_string(buf, "string"); + case Boolean: write_string(buf, "bool"); case Pointer: if info.elem == nil { - buffer_write_string(buf, "rawptr"); + write_string(buf, "rawptr"); } else { - buffer_write_string(buf, "^"); - buffer_write_type(buf, info.elem); + write_string(buf, "^"); + write_type(buf, info.elem); } case Procedure: - buffer_write_string(buf, "proc"); + write_string(buf, "proc"); if info.params == nil { - buffer_write_string(buf, "()"); + write_string(buf, "()"); } else { t := union_cast(^Tuple)info.params; - buffer_write_string(buf, "("); + write_string(buf, "("); for type, i in t.types { - if i > 0 { buffer_write_string(buf, ", "); } - buffer_write_type(buf, type); + if i > 0 { write_string(buf, ", "); } + write_type(buf, type); } - buffer_write_string(buf, ")"); + write_string(buf, ")"); } if info.results != nil { - buffer_write_string(buf, " -> "); - buffer_write_type(buf, info.results); + write_string(buf, " -> "); + write_type(buf, info.results); } case Tuple: count := info.names.count; - if count != 1 { buffer_write_string(buf, "("); } + if count != 1 { write_string(buf, "("); } for name, i in info.names { - if i > 0 { buffer_write_string(buf, ", "); } + if i > 0 { write_string(buf, ", "); } type := info.types[i]; if name.count > 0 { - buffer_write_string(buf, name); - buffer_write_string(buf, ": "); + write_string(buf, name); + write_string(buf, ": "); } - buffer_write_type(buf, type); + write_type(buf, type); } - if count != 1 { buffer_write_string(buf, ")"); } + if count != 1 { write_string(buf, ")"); } case Array: - buffer_write_string(buf, "["); + write_string(buf, "["); fi := Fmt_Info{buf = buf}; fmt_int(^fi, cast(u64)info.count, false, 'd'); - buffer_write_string(buf, "]"); - buffer_write_type(buf, info.elem); + write_string(buf, "]"); + write_type(buf, info.elem); case Dynamic_Array: - buffer_write_string(buf, "[..]"); - buffer_write_type(buf, info.elem); + write_string(buf, "[..]"); + write_type(buf, info.elem); case Slice: - buffer_write_string(buf, "["); - buffer_write_string(buf, "]"); - buffer_write_type(buf, info.elem); + write_string(buf, "["); + write_string(buf, "]"); + write_type(buf, info.elem); case Vector: - buffer_write_string(buf, "[vector "); + write_string(buf, "[vector "); fi := Fmt_Info{buf = buf}; fmt_int(^fi, cast(u64)info.count, false, 'd'); - buffer_write_string(buf, "]"); - buffer_write_type(buf, info.elem); + write_string(buf, "]"); + write_type(buf, info.elem); case Map: - buffer_write_string(buf, "map["); - buffer_write_type(buf, info.key); - buffer_write_byte(buf, ']'); - buffer_write_type(buf, info.value); + write_string(buf, "map["); + write_type(buf, info.key); + write_byte(buf, ']'); + write_type(buf, info.value); case Struct: - buffer_write_string(buf, "struct "); - if info.packed { buffer_write_string(buf, "#packed "); } - if info.ordered { buffer_write_string(buf, "#ordered "); } + write_string(buf, "struct "); + if info.packed { write_string(buf, "#packed "); } + if info.ordered { write_string(buf, "#ordered "); } if info.custom_align { - buffer_write_string(buf, "#align "); + write_string(buf, "#align "); fi := Fmt_Info{buf = buf}; fmt_int(^fi, cast(u64)info.align, false, 'd'); - buffer_write_byte(buf, ' '); + write_byte(buf, ' '); } - buffer_write_byte(buf, '{'); + write_byte(buf, '{'); for name, i in info.names { if i > 0 { - buffer_write_string(buf, ", "); + write_string(buf, ", "); } - buffer_write_string(buf, name); - buffer_write_string(buf, ": "); - buffer_write_type(buf, info.types[i]); + write_string(buf, name); + write_string(buf, ": "); + write_type(buf, info.types[i]); } - buffer_write_byte(buf, '}'); + write_byte(buf, '}'); case Union: - buffer_write_string(buf, "union {"); + write_string(buf, "union {"); cf := info.common_fields; total_count := 0; for name, i in cf.names { if i > 0 { - buffer_write_string(buf, ", "); + write_string(buf, ", "); } - buffer_write_string(buf, name); - buffer_write_string(buf, ": "); - buffer_write_type(buf, cf.types[i]); + write_string(buf, name); + write_string(buf, ": "); + write_type(buf, cf.types[i]); total_count++; } for name, i in info.variant_names { if total_count > 0 || i > 0 { - buffer_write_string(buf, ", "); + write_string(buf, ", "); } - buffer_write_string(buf, name); - buffer_write_byte(buf, '{'); - defer buffer_write_byte(buf, '}'); + write_string(buf, name); + write_byte(buf, '{'); + defer write_byte(buf, '}'); variant_type := type_info_base(info.variant_types[i]); variant := union_cast(^Struct)variant_type; @@ -243,44 +226,44 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { vc := variant.names.count-cf.names.count; for j in 0..vc { if j > 0 { - buffer_write_string(buf, ", "); + write_string(buf, ", "); } index := j + cf.names.count; - buffer_write_string(buf, variant.names[index]); - buffer_write_string(buf, ": "); - buffer_write_type(buf, variant.types[index]); + write_string(buf, variant.names[index]); + write_string(buf, ": "); + write_type(buf, variant.types[index]); } } - buffer_write_string(buf, "}"); + write_string(buf, "}"); case Raw_Union: - buffer_write_string(buf, "raw_union {"); + write_string(buf, "raw_union {"); for name, i in info.names { if i > 0 { - buffer_write_string(buf, ", "); + write_string(buf, ", "); } - buffer_write_string(buf, name); - buffer_write_string(buf, ": "); - buffer_write_type(buf, info.types[i]); + write_string(buf, name); + write_string(buf, ": "); + write_type(buf, info.types[i]); } - buffer_write_string(buf, "}"); + write_string(buf, "}"); case Enum: - buffer_write_string(buf, "enum "); - buffer_write_type(buf, info.base); - buffer_write_string(buf, " {"); + write_string(buf, "enum "); + write_type(buf, info.base); + write_string(buf, " {"); for name, i in info.names { if i > 0 { - buffer_write_string(buf, ", "); + write_string(buf, ", "); } - buffer_write_string(buf, name); + write_string(buf, name); } - buffer_write_string(buf, "}"); + write_string(buf, "}"); } } -bprint :: proc(buf: ^Buffer, args: ..any) -> int { +bprint :: proc(buf: ^[]byte, args: ..any) -> int { fi: Fmt_Info; fi.buf = buf; @@ -288,45 +271,39 @@ bprint :: proc(buf: ^Buffer, args: ..any) -> int { for arg, i in args { is_string := arg.data != nil && types.is_string(arg.type_info); if i > 0 && !is_string && !prev_string { - buffer_write_byte(buf, ' '); + write_byte(buf, ' '); } fmt_value(^fi, args[i], 'v'); prev_string = is_string; } - return buf.length; + return buf.count; } -bprintln :: proc(buf: ^Buffer, args: ..any) -> int { +bprintln :: proc(buf: ^[]byte, args: ..any) -> int { fi: Fmt_Info; fi.buf = buf; for arg, i in args { if i > 0 { - buffer_write_byte(buf, ' '); + write_byte(buf, ' '); } fmt_value(^fi, args[i], 'v'); } - buffer_write_byte(buf, '\n'); - return buf.length; + write_byte(buf, '\n'); + return buf.count; } sprint :: proc(buf: []byte, args: ..any) -> string { - b: Buffer; - b.data = buf; - count := bprint(^b, ..args); - return cast(string)b.data[..b.length]; + count := bprint(^buf, ..args); + return cast(string)buf; } sprintln :: proc(buf: []byte, args: ..any) -> string { - b: Buffer; - b.data = buf; - count := bprintln(^b, ..args); - return cast(string)b.data[..b.length]; + count := bprintln(^buf, ..args); + return cast(string)buf; } sprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string { - b: Buffer; - b.data = buf; - count := bprintf(^b, fmt, ..args); - return cast(string)b.data[..b.length]; + count := bprintf(^buf, fmt, ..args); + return cast(string)buf; } @@ -420,23 +397,23 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) { fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) { assert(verb != 'v'); - buffer_write_string(buf, "%!"); - buffer_write_rune(buf, verb); - buffer_write_byte(buf, '('); + write_string(buf, "%!"); + write_rune(buf, verb); + write_byte(buf, '('); if arg.type_info != nil { - buffer_write_type(buf, arg.type_info); - buffer_write_byte(buf, '='); + write_type(buf, arg.type_info); + write_byte(buf, '='); fmt_value(fi, arg, 'v'); } else { - buffer_write_string(buf, ""); + write_string(buf, ""); } - buffer_write_byte(buf, ')'); + write_byte(buf, ')'); } fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) { match verb { case 't', 'v': - buffer_write_string(buf, b ? "true" : "false"); + write_string(buf, b ? "true" : "false"); default: fmt_bad_verb(fi, verb); } @@ -452,12 +429,10 @@ fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) { pad_byte = '0'; } - count := min(width, fi.buf.data.count-fi.buf.length); - start := fi.buf.length; - for i in start..count { - fi.buf.data[i] = pad_byte; + count := min(width, fi.buf.capacity-fi.buf.count); + for _ in 0..count { + append(fi.buf^, pad_byte); } - fi.buf.length += count; } _write_int :: proc(fi: ^Fmt_Info, u: u64, base: int, neg: bool, digits: string) { @@ -503,7 +478,7 @@ _write_int :: proc(fi: ^Fmt_Info, u: u64, base: int, neg: bool, digits: string) if fi.hash { flags |= strconv.Int_Flag.PREFIX; } if fi.plus { flags |= strconv.Int_Flag.PLUS; } if fi.space { flags |= strconv.Int_Flag.SPACE; } - s := strconv.format_bits(buf[..], u, base, neg, digits, flags); + s := strconv.append_bits(buf[..0], u, base, neg, digits, flags); prev_zero := fi.zero; defer fi.zero = prev_zero; @@ -515,7 +490,7 @@ immutable __DIGITS_LOWER := "0123456789abcdefx"; immutable __DIGITS_UPPER := "0123456789ABCDEFX"; fmt_rune :: proc(fi: ^Fmt_Info, r: rune) { - buffer_write_rune(fi.buf, r); + write_rune(fi.buf, r); } fmt_int :: proc(fi: ^Fmt_Info, u: u64, neg: bool, verb: rune) { @@ -533,7 +508,7 @@ fmt_int :: proc(fi: ^Fmt_Info, u: u64, neg: bool, verb: rune) { if r < 0 || r > utf8.MAX_RUNE { fmt_bad_verb(fi, verb); } else { - buffer_write_string(fi.buf, "U+"); + write_string(fi.buf, "U+"); _write_int(fi, u, 16, false, __DIGITS_UPPER); } @@ -544,16 +519,16 @@ fmt_int :: proc(fi: ^Fmt_Info, u: u64, neg: bool, verb: rune) { _pad :: proc(fi: ^Fmt_Info, s: string) { if !fi.width_set || fi.width == 0 { - buffer_write_string(fi.buf, s); + write_string(fi.buf, s); return; } width := fi.width - utf8.rune_count(s); if fi.minus { // right pad - buffer_write_string(fi.buf, s); + write_string(fi.buf, s); fmt_write_padding(fi, width); } else { // left pad fmt_write_padding(fi, width); - buffer_write_string(fi.buf, s); + write_string(fi.buf, s); } } @@ -570,7 +545,7 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) { prec = fi.prec; } buf: [128]byte; - str := strconv.format_float(buf[1..], v, 'f', prec, bit_size); + str := strconv.append_float(buf[1..1], v, 'f', prec, bit_size); str = cast(string)buf[..str.count+1]; if str[1] == '+' || str[1] == '-' { str = str[1..]; @@ -583,15 +558,15 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) { } if str[1] == 'N' && str[1] == 'I' { - buffer_write_string(fi.buf, str); + write_string(fi.buf, str); return; } if fi.plus || str[0] != '+' { if fi.zero && fi.width_set && fi.width > str.count { - buffer_write_byte(fi.buf, str[0]); + write_byte(fi.buf, str[0]); fmt_write_padding(fi, fi.width - str.count); - buffer_write_string(fi.buf, str[1..]); + write_string(fi.buf, str[1..]); } else { _pad(fi, str); } @@ -607,7 +582,7 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) { fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) { match verb { case 's', 'v': - buffer_write_string(fi.buf, s); + write_string(fi.buf, s); default: fmt_bad_verb(fi, verb); } @@ -623,14 +598,14 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) { } u := cast(u64)cast(uint)p; if !fi.hash || verb == 'v' { - buffer_write_string(fi.buf, "0x"); + write_string(fi.buf, "0x"); } _write_int(fi, u, 16, false, __DIGITS_UPPER); } fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) { if v.type_info == nil || v.data == nil { - buffer_write_string(fi.buf, ""); + write_string(fi.buf, ""); return; } @@ -666,18 +641,18 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) { if types.is_string(e.base) { for val, idx in e.values { if val.i == i { - buffer_write_string(fi.buf, e.names[idx]); + write_string(fi.buf, e.names[idx]); ok = true; break; } } } else if e.values.count == 0 { - buffer_write_string(fi.buf, ""); + write_string(fi.buf, ""); ok = true; } else { for val, idx in e.values { if val.i == i { - buffer_write_string(fi.buf, e.names[idx]); + write_string(fi.buf, e.names[idx]); ok = true; break; } @@ -685,7 +660,7 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) { } if !ok { - buffer_write_string(fi.buf, "!%(BAD ENUM VALUE)"); + write_string(fi.buf, "!%(BAD ENUM VALUE)"); } default: fmt_bad_verb(fi, verb); @@ -697,7 +672,7 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { if v.data == nil || v.type_info == nil { - buffer_write_string(fi.buf, ""); + write_string(fi.buf, ""); return; } @@ -710,18 +685,18 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_bad_verb(fi, verb); return; } - buffer_write_string(fi.buf, info.name); - buffer_write_byte(fi.buf, '{'); + write_string(fi.buf, info.name); + write_byte(fi.buf, '{'); for _, i in b.names { if i > 0 { - buffer_write_string(fi.buf, ", "); + write_string(fi.buf, ", "); } - buffer_write_string(fi.buf, b.names[i]); - buffer_write_string(fi.buf, " = "); + write_string(fi.buf, b.names[i]); + write_string(fi.buf, " = "); data := cast(^byte)v.data + b.offsets[i]; fmt_arg(fi, any{b.types[i], cast(rawptr)data}, 'v'); } - buffer_write_byte(fi.buf, '}'); + write_byte(fi.buf, '}'); default: fmt_value(fi, any{info.base, v.data}, verb); @@ -734,7 +709,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { case Pointer: if v.type_info == type_info(^Type_Info) { - buffer_write_type(fi.buf, (cast(^^Type_Info)v.data)^); + write_type(fi.buf, (cast(^^Type_Info)v.data)^); } else { fmt_pointer(fi, (cast(^rawptr)v.data)^, verb); } @@ -745,11 +720,11 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { return; } - buffer_write_byte(fi.buf, '['); - defer buffer_write_byte(fi.buf, ']'); + write_byte(fi.buf, '['); + defer write_byte(fi.buf, ']'); for i in 0..info.count { if i > 0 { - buffer_write_string(fi.buf, ", "); + write_string(fi.buf, ", "); } data := cast(^byte)v.data + i*info.elem_size; fmt_arg(fi, any{info.elem, cast(rawptr)data}, 'v'); @@ -761,12 +736,12 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { return; } - buffer_write_byte(fi.buf, '['); - defer buffer_write_byte(fi.buf, ']'); + write_byte(fi.buf, '['); + defer write_byte(fi.buf, ']'); array := cast(^Raw_Dynamic_Array)v.data; for i in 0..array.count { if i > 0 { - buffer_write_string(fi.buf, ", "); + write_string(fi.buf, ", "); } data := cast(^byte)array.data + i*info.elem_size; fmt_arg(fi, any{info.elem, cast(rawptr)data}, 'v'); @@ -778,8 +753,8 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { return; } - buffer_write_string(fi.buf, "map["); - defer buffer_write_byte(fi.buf, ']'); + write_string(fi.buf, "map["); + defer write_byte(fi.buf, ']'); entries := ^(cast(^Raw_Dynamic_Map)v.data).entries; gs := union_cast(^Struct)type_info_base(info.generated_struct); ed := union_cast(^Dynamic_Array)type_info_base(gs.types[1]); @@ -788,19 +763,19 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { entry_size := ed.elem_size; for i in 0..entries.count { if i > 0 { - buffer_write_string(fi.buf, ", "); + write_string(fi.buf, ", "); } data := cast(^byte)entries.data + i*entry_size; header := cast(^__Map_Entry_Header)data; if types.is_string(info.key) { - buffer_write_string(fi.buf, header.key.str); + write_string(fi.buf, header.key.str); } else { fi := Fmt_Info{buf = fi.buf}; fmt_arg(^fi, any{info.key, cast(rawptr)^header.key.hash}, 'v'); } - buffer_write_string(fi.buf, "="); + write_string(fi.buf, "="); value := data + entry_type.offsets[2]; fmt_arg(fi, any{info.value, cast(rawptr)value}, 'v'); @@ -812,24 +787,24 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { return; } - buffer_write_byte(fi.buf, '['); - defer buffer_write_byte(fi.buf, ']'); + write_byte(fi.buf, '['); + defer write_byte(fi.buf, ']'); slice := cast(^[]byte)v.data; for i in 0..slice.count { if i > 0 { - buffer_write_string(fi.buf, ", "); + write_string(fi.buf, ", "); } data := slice.data + i*info.elem_size; fmt_arg(fi, any{info.elem, cast(rawptr)data}, 'v'); } case Vector: - buffer_write_byte(fi.buf, '<'); - defer buffer_write_byte(fi.buf, '>'); + write_byte(fi.buf, '<'); + defer write_byte(fi.buf, '>'); for i in 0..info.count { if i > 0 { - buffer_write_string(fi.buf, ", "); + write_string(fi.buf, ", "); } data := cast(^byte)v.data + i*info.elem_size; @@ -837,51 +812,51 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { } case Struct: - buffer_write_byte(fi.buf, '{'); - defer buffer_write_byte(fi.buf, '}'); + write_byte(fi.buf, '{'); + defer write_byte(fi.buf, '}'); for _, i in info.names { if i > 0 { - buffer_write_string(fi.buf, ", "); + write_string(fi.buf, ", "); } - buffer_write_string(fi.buf, info.names[i]); - buffer_write_string(fi.buf, " = "); + write_string(fi.buf, info.names[i]); + write_string(fi.buf, " = "); data := cast(^byte)v.data + info.offsets[i]; fmt_value(fi, any{info.types[i], cast(rawptr)data}, 'v'); } case Union: - buffer_write_byte(fi.buf, '{'); - defer buffer_write_byte(fi.buf, '}'); + write_byte(fi.buf, '{'); + defer write_byte(fi.buf, '}'); cf := info.common_fields; for _, i in cf.names { if i > 0 { - buffer_write_string(fi.buf, ", "); + write_string(fi.buf, ", "); } - buffer_write_string(fi.buf, cf.names[i]); - buffer_write_string(fi.buf, " = "); + write_string(fi.buf, cf.names[i]); + write_string(fi.buf, " = "); data := cast(^byte)v.data + cf.offsets[i]; fmt_value(fi, any{cf.types[i], cast(rawptr)data}, 'v'); } case Raw_Union: - buffer_write_string(fi.buf, "(raw_union)"); + write_string(fi.buf, "(raw_union)"); case Enum: fmt_enum(fi, v, verb); case Procedure: - buffer_write_type(fi.buf, v.type_info); - buffer_write_string(fi.buf, " @ "); + write_type(fi.buf, v.type_info); + write_string(fi.buf, " @ "); fmt_pointer(fi, (cast(^rawptr)v.data)^, 'p'); } } fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { if arg.data == nil || arg.type_info == nil { - buffer_write_string(fi.buf, ""); + write_string(fi.buf, ""); return; } fi.arg = arg; @@ -891,7 +866,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { match a in arg { case ^Type_Info: ti = a; } - buffer_write_type(fi.buf, ti); + write_type(fi.buf, ti); return; } @@ -920,7 +895,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { } -bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int { +bprintf :: proc(b: ^[]byte, fmt: string, args: ..any) -> int { fi := Fmt_Info{}; end := fmt.count; arg_index := 0; @@ -933,7 +908,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int { i++; } if i > prev_i { - buffer_write_string(b, fmt[prev_i..i]); + write_string(b, fmt[prev_i..i]); } if i >= end { break; @@ -974,7 +949,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int { i++; fi.width, arg_index, fi.width_set = int_from_arg(args, arg_index); if !fi.width_set { - buffer_write_string(b, "%!(BAD WIDTH)"); + write_string(b, "%!(BAD WIDTH)"); } if fi.width < 0 { @@ -1005,7 +980,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int { fi.prec_set = false; } if !fi.prec_set { - buffer_write_string(fi.buf, "%!(BAD PRECISION)"); + write_string(fi.buf, "%!(BAD PRECISION)"); } was_prev_index = false; } else { @@ -1022,7 +997,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int { } if i >= end { - buffer_write_string(b, "%!(NO VERB)"); + write_string(b, "%!(NO VERB)"); break; } @@ -1030,11 +1005,11 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int { i += w; if verb == '%' { - buffer_write_byte(b, '%'); + write_byte(b, '%'); } else if !fi.good_arg_index { - buffer_write_string(b, "%!(BAD ARGUMENT NUMBER)"); + write_string(b, "%!(BAD ARGUMENT NUMBER)"); } else if arg_index >= args.count { - buffer_write_string(b, "%!(MISSING ARGUMENT)"); + write_string(b, "%!(MISSING ARGUMENT)"); } else { fmt_arg(^fi, args[arg_index], verb); arg_index++; @@ -1042,19 +1017,19 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int { } if !fi.reordered && arg_index < args.count { - buffer_write_string(b, "%!(EXTRA "); + write_string(b, "%!(EXTRA "); for arg, index in args[arg_index..] { if index > 0 { - buffer_write_string(b, ", "); + write_string(b, ", "); } if arg.data == nil || arg.type_info == nil { - buffer_write_string(b, ""); + write_string(b, ""); } else { fmt_arg(^fi, args[index], 'v'); } } - buffer_write_string(b, ")"); + write_string(b, ")"); } - return b.length; + return b.count; } diff --git a/core/strconv.odin b/core/strconv.odin index 57090cba9..ff78847df 100644 --- a/core/strconv.odin +++ b/core/strconv.odin @@ -18,24 +18,24 @@ parse_bool :: proc(s: string) -> (result: bool, ok: bool) { return false, false; } -format_bool :: proc(buf: []byte, b: bool) -> string { +append_bool :: proc(buf: []byte, b: bool) -> string { s := b ? "true" : "false"; - len := copy(buf, cast([]byte)s); - return cast(string)buf[..len]; + append(buf, ..cast([]byte)s); + return cast(string)buf; } -format_uint :: proc(buf: []byte, u: u64, base: int) -> string { +append_uint :: proc(buf: []byte, u: u64, base: int) -> string { using Int_Flag; - return format_bits(buf, u, base, false, digits, 0); + return append_bits(buf, u, base, false, digits, 0); } -format_int :: proc(buf: []byte, i: i64, base: int) -> string { - return format_bits(buf, cast(u64)i, base, i < 0, digits, 0); +append_int :: proc(buf: []byte, i: i64, base: int) -> string { + return append_bits(buf, cast(u64)i, base, i < 0, digits, 0); } itoa :: proc(buf: []byte, i: int) -> string { - return format_int(buf, cast(i64)i, 10); + return append_int(buf, cast(i64)i, 10); } -format_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string { +append_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string { return cast(string)generic_ftoa(buf, f, fmt, prec, bit_size); } @@ -87,8 +87,8 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [ } else { s = "+Inf"; } - len := copy(buf, cast([]byte)s); - return buf[..len]; + append(buf, ..cast([]byte)s); + return buf; case 0: // denormalized exp++; @@ -190,8 +190,8 @@ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slic c: [2]byte; c[0] = '%'; c[1] = fmt; - len := copy(buf, ..c[..]); - return buf[..len]; + append(buf, ..c[..]); + return buf; } round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) { @@ -265,7 +265,7 @@ MAX_BASE :: 32; immutable digits := "0123456789abcdefghijklmnopqrstuvwxyz"; -format_bits :: proc(buf: []byte, u: u64, base: int, neg: bool, digits: string, flags: Int_Flag) -> string { +append_bits :: proc(buf: []byte, u: u64, base: int, neg: bool, digits: string, flags: Int_Flag) -> string { is_pow2 :: proc(x: i64) -> bool { if (x <= 0) { return false; @@ -274,7 +274,7 @@ format_bits :: proc(buf: []byte, u: u64, base: int, neg: bool, digits: string, f } if base < 2 || base > MAX_BASE { - panic("strconv: illegal base passed to format_bits"); + panic("strconv: illegal base passed to append_bits"); } a: [65]byte; @@ -330,7 +330,7 @@ format_bits :: proc(buf: []byte, u: u64, base: int, neg: bool, digits: string, f } - len := copy(buf, ..a[i..]); - return cast(string)buf[..len]; + append(buf, ..a[i..]); + return cast(string)buf; } diff --git a/src/check_expr.c b/src/check_expr.c index 264a5d072..0e166ef1a 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -5127,6 +5127,10 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint switch (t->kind) { case Type_Basic: if (is_type_string(t)) { + if (se->index3) { + error_node(node, "3-index slice on a string in not needed"); + goto error; + } valid = true; if (o->mode == Addressing_Constant) { max_count = o->value.value_string.len; @@ -5167,14 +5171,20 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint o->mode = Addressing_Value; } + if (se->index3 && (se->high == NULL || se->max == NULL)) { + error(se->close, "2nd and 3rd indices are required in a 3-index slice"); + goto error; + } + i64 indices[2] = {0}; - AstNode *nodes[2] = {se->low, se->high}; + AstNode *nodes[3] = {se->low, se->high, se->max}; for (isize i = 0; i < gb_count_of(nodes); i++) { i64 index = max_count; if (nodes[i] != NULL) { i64 capacity = -1; - if (max_count >= 0) + if (max_count >= 0) { capacity = max_count; + } i64 j = 0; if (check_index_value(c, nodes[i], capacity, &j)) { index = j;