From ccb38c3dc684ece829c7ca1066867cc5212533c3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 12 May 2022 12:54:14 +0100 Subject: [PATCH] Add _safe versions --- core/bytes/bytes.odin | 43 +++++++++++++++++++++++++++++++++++++++ core/strings/strings.odin | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/core/bytes/bytes.odin b/core/bytes/bytes.odin index 09a3ed259..66fd20829 100644 --- a/core/bytes/bytes.odin +++ b/core/bytes/bytes.odin @@ -10,6 +10,12 @@ clone :: proc(s: []byte, allocator := context.allocator, loc := #caller_location return c[:len(s)] } +clone_safe :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: mem.Allocator_Error) { + c := make([]byte, len(s), allocator, loc) or_return + copy(c, s) + return c[:len(s)], nil +} + ptr_from_slice :: proc(str: []byte) -> ^byte { d := transmute(mem.Raw_String)str return d.data @@ -134,6 +140,25 @@ join :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> []byte return b } +join_safe :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> (data: []byte, err: mem.Allocator_Error) { + if len(a) == 0 { + return nil, nil + } + + n := len(sep) * (len(a) - 1) + for s in a { + n += len(s) + } + + b := make([]byte, n, allocator) or_return + i := copy(b, a[0]) + for s in a[1:] { + i += copy(b[i:], sep) + i += copy(b[i:], s) + } + return b, nil +} + concatenate :: proc(a: [][]byte, allocator := context.allocator) -> []byte { if len(a) == 0 { return nil @@ -151,6 +176,24 @@ concatenate :: proc(a: [][]byte, allocator := context.allocator) -> []byte { return b } +concatenate_safe :: proc(a: [][]byte, allocator := context.allocator) -> (data: []byte, err: mem.Allocator_Error) { + if len(a) == 0 { + return nil, nil + } + + n := 0 + for s in a { + n += len(s) + } + b := make([]byte, n, allocator) or_return + i := 0 + for s in a { + i += copy(b[i:], s) + } + return b, nil +} + + @private _split :: proc(s, sep: []byte, sep_save, n: int, allocator := context.allocator) -> [][]byte { s, n := s, n diff --git a/core/strings/strings.odin b/core/strings/strings.odin index a3d9fa93e..2429b451d 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -14,6 +14,13 @@ clone :: proc(s: string, allocator := context.allocator, loc := #caller_location return string(c[:len(s)]) } +// returns a clone of the string `s` allocated using the `allocator` +clone_safe :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (str: string, err: mem.Allocator_Error) { + c := make([]byte, len(s), allocator, loc) or_return + copy(c, s) + return string(c[:len(s)]), nil +} + // returns a clone of the string `s` allocated using the `allocator` as a cstring // a nul byte is appended to the clone, to make the cstring safe clone_to_cstring :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> cstring { @@ -260,6 +267,25 @@ join :: proc(a: []string, sep: string, allocator := context.allocator) -> string return string(b) } +join_safe :: proc(a: []string, sep: string, allocator := context.allocator) -> (str: string, err: mem.Allocator_Error) { + if len(a) == 0 { + return "", nil + } + + n := len(sep) * (len(a) - 1) + for s in a { + n += len(s) + } + + b := make([]byte, n, allocator) or_return + i := copy(b, a[0]) + for s in a[1:] { + i += copy(b[i:], sep) + i += copy(b[i:], s) + } + return string(b), nil +} + /* returns a combined string from the slice of strings `a` without a seperator allocates the string using the `allocator` @@ -285,6 +311,23 @@ concatenate :: proc(a: []string, allocator := context.allocator) -> string { return string(b) } +concatenate_safe :: proc(a: []string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) { + if len(a) == 0 { + return "", nil + } + + n := 0 + for s in a { + n += len(s) + } + b := make([]byte, n, allocator) or_return + i := 0 + for s in a { + i += copy(b[i:], s) + } + return string(b), nil +} + /* `rune_offset` and `rune_length` are in runes, not bytes. If `rune_length` <= 0, then it'll return the remainder of the string starting at `rune_offset`.