Browse Source

Add _safe versions

gingerBill 3 years ago
parent
commit
ccb38c3dc6
2 changed files with 86 additions and 0 deletions
  1. 43 0
      core/bytes/bytes.odin
  2. 43 0
      core/strings/strings.odin

+ 43 - 0
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

+ 43 - 0
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`.