Browse Source

strings.split; strings.index; eprint* over print*_err;

gingerBill 5 years ago
parent
commit
4e8a801b35

+ 12 - 6
core/fmt/fmt.odin

@@ -59,12 +59,18 @@ fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
 
 
 
 
 // print* procedures return the number of bytes written
 // print* procedures return the number of bytes written
-print       :: proc(args: ..any)              -> int { return fprint(context.stdout, ..args); }
-print_err   :: proc(args: ..any)              -> int { return fprint(context.stderr, ..args); }
-println     :: proc(args: ..any)              -> int { return fprintln(context.stdout, ..args); }
-println_err :: proc(args: ..any)              -> int { return fprintln(context.stderr, ..args); }
-printf      :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stdout, fmt, ..args); }
-printf_err  :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stderr, fmt, ..args); }
+print   :: proc(args: ..any)              -> int { return fprint(context.stdout, ..args); }
+println :: proc(args: ..any)              -> int { return fprintln(context.stdout, ..args); }
+printf  :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stdout, fmt, ..args); }
+
+eprint   :: proc(args: ..any)              -> int { return fprint(context.stderr, ..args); }
+eprintln :: proc(args: ..any)              -> int { return fprintln(context.stderr, ..args); }
+eprintf  :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stderr, fmt, ..args); }
+
+
+@(deprecated="prefer eprint")   print_err   :: proc(args: ..any)              -> int { return eprint(..args); }
+@(deprecated="prefer eprintf")  println_err :: proc(args: ..any)              -> int { return eprintln(..args); }
+@(deprecated="prefer eprintln") printf_err  :: proc(fmt: string, args: ..any) -> int { return eprintf(fmt, ..args); }
 
 
 
 
 // aprint* procedures return a string that was allocated with the current context
 // aprint* procedures return a string that was allocated with the current context

+ 2 - 4
core/reflect/types.odin

@@ -304,10 +304,8 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
 			write_byte(buf, info.signed ? 'i' : 'u');
 			write_byte(buf, info.signed ? 'i' : 'u');
 			write_i64(buf, i64(8*ti.size), 10);
 			write_i64(buf, i64(8*ti.size), 10);
 			switch info.endianness {
 			switch info.endianness {
-			case rt.Type_Info_Endianness.Little:
-				write_string(buf, "le");
-			case rt.Type_Info_Endianness.Big:
-				write_string(buf, "be");
+			case .Little: write_string(buf, "le");
+			case .Big:    write_string(buf, "be");
 			}
 			}
 		}
 		}
 	case rt.Type_Info_Rune:
 	case rt.Type_Info_Rune:

+ 2 - 2
core/runtime/core.odin

@@ -40,7 +40,7 @@ Type_Info_Enum_Value :: union {
 	u8, u16, u32, u64, uint, uintptr,
 	u8, u16, u32, u64, uint, uintptr,
 };
 };
 
 
-Type_Info_Endianness :: enum u8 {
+Platform_Endianness :: enum u8 {
 	Platform = 0,
 	Platform = 0,
 	Little   = 1,
 	Little   = 1,
 	Big      = 2,
 	Big      = 2,
@@ -48,7 +48,7 @@ Type_Info_Endianness :: enum u8 {
 
 
 // Variant Types
 // Variant Types
 Type_Info_Named      :: struct {name: string, base: ^Type_Info};
 Type_Info_Named      :: struct {name: string, base: ^Type_Info};
-Type_Info_Integer    :: struct {signed: bool, endianness: Type_Info_Endianness};
+Type_Info_Integer    :: struct {signed: bool, endianness: Platform_Endianness};
 Type_Info_Rune       :: struct {};
 Type_Info_Rune       :: struct {};
 Type_Info_Float      :: struct {};
 Type_Info_Float      :: struct {};
 Type_Info_Complex    :: struct {};
 Type_Info_Complex    :: struct {};

+ 4 - 0
core/strconv/strconv.odin

@@ -205,7 +205,11 @@ itoa :: proc(buf: []byte, i: int) -> string {
 atoi :: proc(s: string) -> int {
 atoi :: proc(s: string) -> int {
 	return parse_int(s);
 	return parse_int(s);
 }
 }
+atof :: proc(s: string) -> f64 {
+	return parse_f64(s);
+}
 
 
+ftoa :: append_float;
 append_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 string(generic_ftoa(buf, f, fmt, prec, bit_size));
 	return string(generic_ftoa(buf, f, fmt, prec, bit_size));
 }
 }

+ 4 - 0
core/strings/builder.odin

@@ -21,6 +21,10 @@ grow_builder :: proc(b: ^Builder, cap: int) {
 	reserve(&b.buf, cap);
 	reserve(&b.buf, cap);
 }
 }
 
 
+reset_builder :: proc(b: ^Builder) {
+	clear(&b.buf);
+}
+
 builder_from_slice :: proc(backing: []byte) -> Builder {
 builder_from_slice :: proc(backing: []byte) -> Builder {
 	s := transmute(mem.Raw_Slice)backing;
 	s := transmute(mem.Raw_Slice)backing;
 	d := mem.Raw_Dynamic_Array{
 	d := mem.Raw_Dynamic_Array{

+ 147 - 3
core/strings/strings.odin

@@ -155,6 +155,73 @@ concatenate :: proc(a: []string, allocator := context.allocator) -> string {
 	return string(b);
 	return string(b);
 }
 }
 
 
+@private
+_split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocator) -> []string {
+	s, n := s_, n_;
+
+	if n == 0 {
+		return nil;
+	}
+
+	if sep == "" {
+		l := utf8.rune_count_in_string(s);
+		if n < 0 || n > l {
+			n = l;
+		}
+
+		res := make([dynamic]string, n);
+		for i := 0; i < n-1; i += 1 {
+			r, w := utf8.decode_rune_in_string(s);
+			res[i] = s[:w];
+			s = s[w:];
+		}
+		if n > 0 {
+			res[n-1] = s;
+		}
+		return res[:];
+	}
+
+	if n < 0 {
+		n = count(s, sep) + 1;
+	}
+
+	res := make([dynamic]string, n);
+
+	n -= 1;
+
+	i := 0;
+	for ; i < n; i += 1 {
+		m := index(s, sep);
+		if m < 0 {
+			break;
+		}
+		res[i] = s[:m+sep_save];
+		s = s[m+len(sep):];
+	}
+	res[i] = s;
+
+	return res[:i+1];
+}
+
+split :: inline proc(s, sep: string, allocator := context.allocator) -> []string {
+	return _split(s, sep, 0, -1, allocator);
+}
+
+split_n :: inline proc(s, sep: string, n: int, allocator := context.allocator) -> []string {
+	return _split(s, sep, 0, n, allocator);
+}
+
+split_after :: inline proc(s, sep: string, allocator := context.allocator) -> []string {
+	return _split(s, sep, len(sep), -1, allocator);
+}
+
+split_after_n :: inline proc(s, sep: string, n: int, allocator := context.allocator) -> []string {
+	return _split(s, sep, len(sep), n, allocator);
+}
+
+
+
+
 index_byte :: proc(s: string, c: byte) -> int {
 index_byte :: proc(s: string, c: byte) -> int {
 	for i := 0; i < len(s); i += 1 {
 	for i := 0; i < len(s); i += 1 {
 		if s[i] == c do return i;
 		if s[i] == c do return i;
@@ -170,7 +237,25 @@ last_index_byte :: proc(s: string, c: byte) -> int {
 	return -1;
 	return -1;
 }
 }
 
 
+
+
+@private PRIME_RABIN_KARP :: 16777619;
+
 index :: proc(s, substr: string) -> int {
 index :: proc(s, substr: string) -> int {
+	hash_str_rabin_karp :: proc(s: string) -> (hash: u32 = 0, pow: u32 = 1) {
+		for i := 0; i < len(s); i += 1 {
+			hash = hash*PRIME_RABIN_KARP + u32(s[i]);
+		}
+		sq := u32(PRIME_RABIN_KARP);
+		for i := len(s); i > 0; i >>= 1 {
+			if (i & 1) != 0 {
+				pow *= sq;
+			}
+			sq *= sq;
+		}
+		return;
+	}
+
 	n := len(substr);
 	n := len(substr);
 	switch {
 	switch {
 	case n == 0:
 	case n == 0:
@@ -186,9 +271,68 @@ index :: proc(s, substr: string) -> int {
 		return -1;
 		return -1;
 	}
 	}
 
 
-	for i := 0; i < len(s)-n+1; i += 1 {
-		x := s[i:i+n];
-		if x == substr {
+	hash, pow := hash_str_rabin_karp(substr);
+	h: u32;
+	for i := 0; i < n; i += 1 {
+		h = h*PRIME_RABIN_KARP + u32(s[i]);
+	}
+	if h == hash && s[:n] == substr {
+		return 0;
+	}
+	for i := n; i < len(s); /**/ {
+		h *= PRIME_RABIN_KARP;
+		h += u32(s[i]);
+		h -= pow * u32(s[i-n]);
+		i += 1;
+		if h == hash && s[i-n:i] == substr {
+			return i - n;
+		}
+	}
+	return -1;
+}
+
+last_index :: proc(s, substr: string) -> int {
+	hash_str_rabin_karp_reverse :: proc(s: string) -> (hash: u32 = 0, pow: u32 = 1) {
+		for i := len(s) - 1; i >= 0; i -= 1 {
+			hash = hash*PRIME_RABIN_KARP + u32(s[i]);
+		}
+		sq := u32(PRIME_RABIN_KARP);
+		for i := len(s); i > 0; i >>= 1 {
+			if (i & 1) != 0 {
+				pow *= sq;
+			}
+			sq *= sq;
+		}
+		return;
+	}
+
+	n := len(substr);
+	switch {
+	case n == 0:
+		return len(s);
+	case n == 1:
+		return last_index_byte(s, substr[0]);
+	case n == len(s):
+		return substr == s ? 0 : -1;
+	case n > len(s):
+		return -1;
+	}
+
+	hash, pow := hash_str_rabin_karp_reverse(substr);
+	last := len(s) - n;
+	h: u32;
+	for i := len(s)-1; i >= last; i -= 1 {
+		h = h*PRIME_RABIN_KARP + u32(s[i]);
+	}
+	if h == hash && s[last:] == substr {
+		return last;
+	}
+
+	for i := last-1; i >= 0; i -= 1 {
+		h *= PRIME_RABIN_KARP;
+		h += u32(s[i]);
+		h -= pow * u32(s[i+n]);
+		if h == hash && s[i:i+n] == substr {
 			return i;
 			return i;
 		}
 		}
 	}
 	}

+ 11 - 1
examples/demo/demo.odin

@@ -4,6 +4,7 @@ import "core:fmt"
 import "core:mem"
 import "core:mem"
 import "core:os"
 import "core:os"
 import "core:reflect"
 import "core:reflect"
+import "core:strings"
 import "intrinsics"
 import "intrinsics"
 
 
 when os.OS == "windows" {
 when os.OS == "windows" {
@@ -1189,7 +1190,15 @@ where_clauses :: proc() {
 }
 }
 
 
 main :: proc() {
 main :: proc() {
-	when true {
+    x := "foobarbaz";
+    i : int;
+    i = strings.last_index(x, "foo"); fmt.println(i);
+    i = strings.last_index(x, "bar"); fmt.println(i);
+    i = strings.last_index(x, "baz"); fmt.println(i);
+    i = strings.last_index(x, "asd"); fmt.println(i);
+    i = strings.last_index(x, "a"); fmt.println(i);
+    i = strings.last_index(x, "ba"); fmt.println(i);
+	when false {
 		general_stuff();
 		general_stuff();
 		union_type();
 		union_type();
 		parametric_polymorphism();
 		parametric_polymorphism();
@@ -1212,3 +1221,4 @@ main :: proc() {
 		where_clauses();
 		where_clauses();
 	}
 	}
 }
 }
+

+ 1 - 1
src/build_settings.cpp

@@ -55,7 +55,7 @@ TargetEndianKind target_endians[TargetArch_COUNT] = {
 
 
 
 
 
 
-String const ODIN_VERSION = str_lit("0.10.1");
+String const ODIN_VERSION = str_lit("0.10.2");