@@ -495,6 +495,75 @@ pub fn (s string) replace_each(vals []string) string {
495
495
}
496
496
}
497
497
498
+ // replace_char replaces all occurences of the character `rep` multiple occurences of the character passed in `with` with respect to `repeat`.
499
+ // Example: assert '\tHello!'.replace_char(`\t`,` `,8) == ' Hello!'
500
+ [direct_array_access ]
501
+ pub fn (s string) replace_char (rep u8 , with u8 , repeat int ) string {
502
+ $if ! no_bounds_checking ? {
503
+ if repeat < = 0 {
504
+ panic ('string.replace_char(): tab length too short' )
505
+ }
506
+ }
507
+ if s.len == 0 {
508
+ return s.clone ()
509
+ }
510
+ // TODO Allocating ints is expensive. Should be a stack array
511
+ // - string.replace()
512
+ mut idxs := []int {cap: s.len}
513
+ defer {
514
+ unsafe { idxs.free () }
515
+ }
516
+ // No need to do a contains(), it already traverses the entire string
517
+ for i, ch in s {
518
+ if ch == rep { // Found char? Mark its location
519
+ idxs << i
520
+ }
521
+ }
522
+ if idxs.len == 0 {
523
+ return s.clone ()
524
+ }
525
+ // Now we know the number of replacements we need to do and we can calc the len of the new string
526
+ new_len := s.len + idxs.len * (repeat - 1 )
527
+ mut b := unsafe { malloc_noscan (new_len + 1 ) } // add space for the null byte at the end
528
+ // Fill the new string
529
+ mut b_i := 0
530
+ mut s_idx := 0
531
+ for rep_pos in idxs {
532
+ for i in s_idx .. rep_pos { // copy everything up to piece being replaced
533
+ unsafe {
534
+ b[b_i] = s[i]
535
+ }
536
+ b_i++
537
+ }
538
+ s_idx = rep_pos + 1 // move string index past replacement
539
+ for _ in 0 .. repeat { // copy replacement piece
540
+ unsafe {
541
+ b[b_i] = with
542
+ }
543
+ b_i++
544
+ }
545
+ }
546
+ if s_idx < s.len { // if any original after last replacement, copy it
547
+ for i in s_idx .. s.len {
548
+ unsafe {
549
+ b[b_i] = s[i]
550
+ }
551
+ b_i++
552
+ }
553
+ }
554
+ unsafe {
555
+ b[new_len] = 0
556
+ return tos (b, new_len)
557
+ }
558
+ }
559
+
560
+ // normalize_tabs replaces all tab characters with `tab_len` amount of spaces
561
+ // Example: assert '\t\tpop rax\t; pop rax'.normalize_tabs(2) == ' pop rax ; pop rax'
562
+ [inline ]
563
+ pub fn (s string) normalize_tabs (tab_len int ) string {
564
+ return s.replace_char (`\t ` , ` ` , tab_len)
565
+ }
566
+
498
567
// bool returns `true` if the string equals the word "true" it will return `false` otherwise.
499
568
pub fn (s string) bool () bool {
500
569
return s == 'true' || s == 't' // TODO t for pg, remove
0 commit comments