Ctrl K
ComunidadGuías…

std/string.zc

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import "./core.zc"
import "./vec.zc"
import "./option.zc"

fn _z_internal_str_case_cmp(s1: char*, s2: char*) -> int {
    let i = 0;
    while (true) {
        let c1 = (int)((byte)s1[i]);
        let c2 = (int)((byte)s2[i]);
        
        // Convert to lowercase for comparison
        let lc1 = if (c1 >= (int)'A' && c1 <= (int)'Z') { c1 + 32 } else { c1 };
        let lc2 = if (c2 >= (int)'A' && c2 <= (int)'Z') { c2 + 32 } else { c2 };
        
        if (lc1 != lc2) {
            return lc1 - lc2;
        }
        
        if (c1 == 0) {
            break;
        }
        i = i + 1;
    }
    return 0;
}

struct String {
    vec: Vec<char>;
}

struct StringCharsIter {
    data: char*;
    len: usize;
    pos: usize;
}

impl StringCharsIter {
    fn next(self) -> Option<rune> {
        if (self.pos >= self.len) {
            return Option<rune>::None();
        }
        
        let c = (byte)self.data[self.pos];
        let seq = String::_utf8_seq_len((char)c);
        
        if (self.pos + seq > self.len) {
            self.pos = self.len;
            return Option<rune>::None();
        }

        let val: rune = 0;
        if (seq == 1) {
            val = (rune)c;
        } else if (seq == 2) {
            val = (rune)(((int)(c & 0x1F) << 6) | ((int)(byte)self.data[self.pos+1] & 0x3F));
        } else if (seq == 3) {
            val = (rune)(((int)(c & 0x0F) << 12) | (((int)(byte)self.data[self.pos+1] & 0x3F) << 6) | ((int)(byte)self.data[self.pos+2] & 0x3F));
        } else if (seq == 4) {
            val = (rune)(((int)(c & 0x07) << 18) | (((int)(byte)self.data[self.pos+1] & 0x3F) << 12) | (((int)(byte)self.data[self.pos+2] & 0x3F) << 6) | ((int)(byte)self.data[self.pos+3] & 0x3F));
        }
        
        self.pos = self.pos + seq;
        return Option<rune>::Some(val);
    }

    /// Returns an iterator over the code points.
    fn iterator(self) -> StringCharsIter {
        return self;
    }
}

impl String {
    /// Creates a new String from a C string.
    fn new(s: char*) -> String {
        let len = strlen(s);
        let v = Vec<char>::with_capacity(len + 1);
        if (len > 0) {
            memcpy(v.data, s, len * sizeof(char));
        }
        v.len = len + 1;
        v.data[len] = 0;
        
        let d = v.data;
        let l = v.len;
        let c = v.cap;
        v.forget();
        
        return String { vec: Vec<char> { data: d, len: l, cap: c } };
    }

    /// Creates a new String from a C string (alias for `new`).
    fn from(s: char*) -> String {
        return String::new(s);
    }

    /// Creates a String from a single rune.
    fn from_rune(r: rune) -> String {
        let s = String::new("");
        s.push_rune(r);
        return s;
    }

    /// Creates a String from an array of runes.
    fn from_runes(runes: rune*, count: usize) -> String {
        let s = String::new("");
        for (let i: usize = 0; i < count; i = i + 1) {
            s.push_rune(runes[i]);
        }
        return s;
    }

    /// Returns the underlying NUL-terminated C string.
    fn c_str(self) -> char* {
        return self.vec.data;
    }

    /// Returns a `char*` view of the string.
    fn to_string(self) -> char* {
        return self.c_str();
    }

    /// Returns an independent copy with its own buffer.
    fn clone(self) -> String {
        return String { vec: self.vec.clone() };
    }

    /// Frees the string memory (deprecated; use `free`).
    fn destroy(self) {
        self.free();
    }

    /// Detaches the internal buffer without freeing it.
    fn forget(self) {
        self.vec.forget();
    }
    
    /// Appends another String in place.
    fn append(self, other: String*) {
        if (self.vec.len > 0) {
            self.vec.len = self.vec.len - 1;
        }
        let other_len = (*other).vec.len;
        let new_len = self.vec.len + other_len;
        self.vec.grow_to_fit(new_len);
        memcpy(self.vec.data + self.vec.len, (*other).vec.data, other_len * sizeof(char));
        self.vec.len = new_len;
    }

    /// Appends a C string in place.
    fn append_c(self, s: char*) {
        if (self.vec.len > 0) {
            self.vec.len = self.vec.len - 1;
        }
        let slen = strlen(s);
        let new_len = self.vec.len + slen + 1;
        self.vec.grow_to_fit(new_len);
        memcpy(self.vec.data + self.vec.len, s, slen * sizeof(char));
        self.vec.len = new_len;
        self.vec.data[new_len - 1] = 0;
    }

    /// Appends a rune (UTF-8 encoded).
    fn push_rune(self, r: rune) {
        if (self.vec.len > 0) {
            self.vec.len = self.vec.len - 1;
        }
        
        let val = (uint32_t)r;
        if (val < 0x80) {
            self.vec.push((char)val);
        } else if (val < 0x800) {
            self.vec.push((char)(0xC0 | (val >> 6)));
            self.vec.push((char)(0x80 | (val & 0x3F)));
        } else if (val < 0x10000) {
            self.vec.push((char)(0xE0 | (val >> 12)));
            self.vec.push((char)(0x80 | ((val >> 6) & 0x3F)));
            self.vec.push((char)(0x80 | (val & 0x3F)));
        } else {
            self.vec.push((char)(0xF0 | (val >> 18)));
            self.vec.push((char)(0x80 | ((val >> 12) & 0x3F)));
            self.vec.push((char)(0x80 | ((val >> 6) & 0x3F)));
            self.vec.push((char)(0x80 | (val & 0x3F)));
        }
        self.vec.push(0);
    }

    fn append_c_ptr(ptr: String*, s: char*) {
        if (ptr.vec.len > 0) {
            ptr.vec.len = ptr.vec.len - 1;
        }
        let slen = strlen(s);
        let new_len = ptr.vec.len + slen + 1;
        ptr.vec.grow_to_fit(new_len);
        memcpy(ptr.vec.data + ptr.vec.len, s, slen * sizeof(char));
        ptr.vec.len = new_len;
        ptr.vec.data[new_len - 1] = 0;
    }

    /// Returns a new String concatenating self and other.
    fn add(self, other: String*) -> String {
        let new_s = String::from(self.c_str());
        (&new_s).append(other);
        
        let d = new_s.vec.data;
        let l = new_s.vec.len;
        let c = new_s.vec.cap;
        new_s.forget();
        
        return String { vec: Vec<char> { data: d, len: l, cap: c } };
    }

    /// Appends other in place.
    fn add_assign(self, other: String*) {
        self.append(other);
    }

    /// Returns whether this String equals another.
    fn eq(self, other: String*) -> bool {
        let zero: c_int = 0;
        return strcmp(self.c_str(), (*other).c_str()) == zero;
    }

    /// Returns whether this String differs from another.
    fn neq(self, other: String*) -> bool {
        return !self.eq(other);
    }

    /// Lexicographic comparison: returns <0, 0, or >0.
    fn compare(self, other: String*) -> int {
        return strcmp(self.c_str(), (*other).c_str());
    }

    /// Returns whether this String is less than another.
    fn lt(self, other: String*) -> bool {
        return self.compare(other) < 0;
    }

    /// Returns whether this String is greater than another.
    fn gt(self, other: String*) -> bool {
        return self.compare(other) > 0;
    }

    /// Returns whether this String is <= another.
    fn le(self, other: String*) -> bool {
        return self.compare(other) <= 0;
    }

    /// Returns whether this String is >= another.
    fn ge(self, other: String*) -> bool {
        return self.compare(other) >= 0;
    }

    /// Case-insensitive lexicographic comparison.
    fn compare_ignore_case(self, other: String*) -> int {
        return _z_internal_str_case_cmp(self.vec.data, (*other).vec.data);
    }

    /// Case-insensitive equality.
    fn eq_ignore_case(self, other: String*) -> bool {
        let zero: int = 0;
        return self.compare_ignore_case(other) == zero;
    }

    /// Returns whether this String equals a C string.
    fn eq_str(self, s: char*) -> bool {
        let zero: c_int = 0;
        return strcmp(self.c_str(), s) == zero;
    }

    /// Returns the length in bytes (not code points).
    fn length(self) -> usize {
        if (self.vec.len == 0) { return 0; }
        return self.vec.len - 1;
    }
    
    /// Returns a new String of `len` bytes starting at `start`.
    fn substring(self, start: usize, len: usize) -> String {
        if (start + len > self.length()) {
            panic("substring out of bounds");
        }
        let v = Vec<char>::with_capacity(len + 1);
        if (len > 0) {
            memcpy(v.data, self.vec.data + start, len * sizeof(char));
        }
        v.len = len + 1;
        v.data[len] = 0;
        
        let d = v.data;
        let l = v.len;
        let c = v.cap;
        v.forget();
        
        return String { vec: Vec<char> { data: d, len: l, cap: c } };
    }
    /// Returns whether the substring `target` occurs.
    fn contains_str(self, target: char*) -> bool {
        return self.find_str(target).is_some();
    }

    /// Returns the first index of `target`, or `None`.
    fn find_str(self, target: char*) -> Option<usize> {
        let t_len = strlen(target);
        if t_len == 0 { return Option<usize>::Some(0); }
        let s_len = self.length();
        if t_len > s_len { return Option<usize>::None(); }
        
        for (let i: usize = 0; i <= s_len - t_len; i = i + 1) {
            let is_match = true;
            for (let k: usize = 0; k < t_len; k = k + 1) {
                if self.vec.get(i + k) != target[k] {
                    is_match = false;
                    break;
                }
            }
            if is_match { return Option<usize>::Some(i); }
        }
        return Option<usize>::None();
    }

    /// Returns all indices where `target` occurs.
    fn find_all_str(self, target: char*) -> Vec<usize> {
        let indices = Vec<usize>::new();
        let t_len = strlen(target);
        if t_len == 0 { return indices; }
        let s_len = self.length();
        if t_len > s_len { return indices; }

        for (let i: usize = 0; i <= s_len - t_len; i = i + 1) {
            let is_match = true;
            for (let k: usize = 0; k < t_len; k = k + 1) {
                if self.vec.get(i + k) != target[k] {
                    is_match = false;
                    break;
                }
            }
            if is_match {
                indices.push(i);
                // Optional: i = i + t_len - 1; (Un-comment to avoid overlapping matches)
            }
        }
        return indices;
    }

    /// Returns a new lowercase copy.
    fn to_lowercase(self) -> String {
        let len = self.length();
        let v = Vec<char>::with_capacity(len + 1);
        for (let i: usize = 0; i < len; i = i + 1) {
            let c = self.vec.get(i);
            if (c >= 'A' && c <= 'Z') {
                v.push((char)((int)c + 32));
            } else {
                v.push(c);
            }
        }
        v.push(0);
        let d = v.data;
        let l = v.len;
        let c_cap = v.cap;
        v.forget();
        return String { vec: Vec<char> { data: d, len: l, cap: c_cap } };
    }

    /// Returns a new string padded on the right to `target_len`.
    fn pad_right(self, target_len: usize, pad_char: char) -> String {
        let current_len = self.length();
        if (current_len >= target_len) {
            return String::from(self.c_str());
        }
        
        let v = Vec<char>::with_capacity(target_len + 1);
        if (current_len > 0) {
            memcpy(v.data, self.vec.data, current_len * sizeof(char));
        }
        v.len = current_len;
        for (let i: usize = current_len; i < target_len; i = i + 1) {
            v.push(pad_char);
        }
        v.push(0);
        
        let d = v.data;
        let l = v.len;
        let c_cap = v.cap;
        v.forget();
        return String { vec: Vec<char> { data: d, len: l, cap: c_cap } };
    }

    /// Returns a new string padded on the left to `target_len`.
    fn pad_left(self, target_len: usize, pad_char: char) -> String {
        let current_len = self.length();
        if (current_len >= target_len) {
            return String::from(self.c_str());
        }
        
        let v = Vec<char>::with_capacity(target_len + 1);
        let diff = target_len - current_len;
        for (let i: usize = 0; i < diff; i = i + 1) {
            v.push(pad_char);
        }
        if (current_len > 0) {
            memcpy(v.data + diff, self.vec.data, current_len * sizeof(char));
        }
        v.len = v.len + current_len;
        v.push(0);
        
        let d = v.data;
        let l = v.len;
        let c_cap = v.cap;
        v.forget();
        return String { vec: Vec<char> { data: d, len: l, cap: c_cap } };
    }

    /// Returns a new uppercase copy.
    fn to_uppercase(self) -> String {
        let len = self.length();
        let v = Vec<char>::with_capacity(len + 1);
        for (let i: usize = 0; i < len; i = i + 1) {
            let c = self.vec.get(i);
            if (c >= 'a' && c <= 'z') {
                v.push((char)((int)c - 32));
            } else {
                v.push(c);
            }
        }
        v.push(0);
        let d = v.data;
        let l = v.len;
        let c_cap = v.cap;
        v.forget();
        return String { vec: Vec<char> { data: d, len: l, cap: c_cap } };
    }

    /// Returns the first index of the character `target`, or `None`.
    fn find(self, target: char) -> Option<usize> {
        let len = self.length();
        for (let i: usize = 0; i < len; i = i + 1) {
            if (self.vec.get(i) == target) {
                return Option<usize>::Some(i);
            }
        }
        return Option<usize>::None();
    }

    /// Prints the string to stdout.
    fn print(self) {
        printf("%s", self.c_str());
        fflush(stdout);
    }

    /// Prints the string to stdout followed by a newline.
    fn println(self) {
        printf("%s\n", self.c_str());
    }
    
    /// Returns whether the string is empty.
    fn is_empty(self) -> bool {
        return self.length() == 0;
    }
    
    /// Returns whether the character `target` occurs.
    fn contains(self, target: char) -> bool {
        return self.find(target).is_some();
    }
    
    /// Returns whether the string starts with `prefix`.
    fn starts_with(self, prefix: char*) -> bool {
        let plen = strlen(prefix);
        if plen > self.length() { return false; }
        let zero: c_int = 0;
        return strncmp(self.c_str(), prefix, plen) == zero;
    }
    
    /// Returns whether the string ends with `suffix`.
    fn ends_with(self, suffix: char*) -> bool {
        let slen = strlen(suffix);
        let len = self.length();
        if slen > len { return false; }
        let offset = (int)(len - slen);
        let zero: c_int = 0;
        return strcmp(self.c_str() + offset, suffix) == zero;
    }
    
    /// Ensures capacity for at least `cap` bytes.
    fn reserve(self, cap: usize) {
        self.vec.grow_to_fit(cap + 1);
    }

    /// Frees the string memory.
    fn free(self) {
        self.vec.free();
    }

    fn _utf8_seq_len(first_byte: char) -> usize {
        let b = (int)first_byte;
        if ((b & 0x80) == 0) { return 1; }
        if ((b & 0xE0) == 0xC0) { return 2; }
        if ((b & 0xF0) == 0xE0) { return 3; }
        if ((b & 0xF8) == 0xF0) { return 4; }
        return 1; // Fallback
    }

    /// Returns the number of Unicode code points.
    fn utf8_len(self) -> usize {
        let count: usize = 0;
        let i: usize = 0;
        let len = self.length();
        while i < len {
            let c = self.vec.get(i);
            i = i + String::_utf8_seq_len(c);
            count = count + 1;
        }
        return count;
    }

    /// Returns the code point at byte index `idx` as a String.
    fn utf8_at(self, idx: usize) -> String {
        let count: usize = 0;
        let i: usize = 0;
        let len = self.length();
        while i < len {
            let c = self.vec.get(i);
            let seq = String::_utf8_seq_len(c);
            
            if (count == idx) {
                return self.substring(i, seq);
            }
            
            i = i + seq;
            count = count + 1;
        }
        return String::new("");
    }

    /// Returns the code point at byte index `idx` as a rune.
    fn utf8_get(self, idx: usize) -> rune {
        let count: usize = 0;
        let i: usize = 0;
        let len = self.length();
        while i < len {
            let c = (byte)self.vec.get(i);
            let seq = String::_utf8_seq_len((char)c);
            
            if (count == idx) {
                if (seq == 1) { return (rune)c; }
                if (seq == 2) { return (rune)(((int)(c & 0x1F) << 6) | ((int)(byte)self.vec.get(i + 1) & 0x3F)); }
                if (seq == 3) { return (rune)(((int)(c & 0x0F) << 12) | (((int)(byte)self.vec.get(i + 1) & 0x3F) << 6) | ((int)(byte)self.vec.get(i + 2) & 0x3F)); }
                if (seq == 4) { return (rune)(((int)(c & 0x07) << 18) | (((int)(byte)self.vec.get(i + 1) & 0x3F) << 12) | (((int)(byte)self.vec.get(i + 2) & 0x3F) << 6) | ((int)(byte)self.vec.get(i + 3) & 0x3F)); }
            }
            
            i = i + seq;
            count = count + 1;
        }
        return (rune)0;
    }

    /// Returns a Vec of the code points.
    fn runes(self) -> Vec<rune> {
        let v = Vec<rune>::new();
        let i: usize = 0;
        let len = self.length();
        while i < len {
            let c = (byte)self.vec.get(i);
            let seq = String::_utf8_seq_len((char)c);
            let val: rune = 0;
            if (seq == 1) {
                val = (rune)c;
            } else if (seq == 2) {
                val = (rune)(((int)(c & 0x1F) << 6) | ((int)(byte)self.vec.get(i + 1) & 0x3F));
            } else if (seq == 3) {
                val = (rune)(((int)(c & 0x0F) << 12) | (((int)(byte)self.vec.get(i + 1) & 0x3F) << 6) | ((int)(byte)self.vec.get(i + 2) & 0x3F));
            } else if (seq == 4) {
                val = (rune)(((int)(c & 0x07) << 18) | (((int)(byte)self.vec.get(i + 1) & 0x3F) << 12) | (((int)(byte)self.vec.get(i + 2) & 0x3F) << 6) | ((int)(byte)self.vec.get(i + 3) & 0x3F));
            }
            v.push(val);
            i = i + seq;
        }
        return v;
    }

    /// Returns an iterator over the code points.
    fn iterator(self) -> StringCharsIter {
        return self.chars();
    }

    /// Returns an iterator over the code points.
    fn chars(self) -> StringCharsIter {
        return StringCharsIter {
            data: self.c_str(),
            len: self.length(),
            pos: 0
        };
    }

    /// Creates a String from a Vec of runes.
    fn from_runes_vec(runes: Vec<rune>) -> String {
        let s = String::new("");
        for (let i: usize = 0; i < runes.len; i = i + 1) {
            s.push_rune(runes.get(i));
        }
        return s;
    }

    /// Inserts a rune at byte index `idx`.
    fn insert_rune(self, idx: usize, r: rune) {
        let i: usize = 0;
        let count: usize = 0;
        let len = self.length();
        while i < len && count < idx {
            i = i + String::_utf8_seq_len(self.vec.get(i));
            count = count + 1;
        }
        
        let val = (uint32_t)r;
        if (val < 0x80) {
            self.vec.insert(i, (char)val);
        } else if (val < 0x800) {
            self.vec.insert(i, (char)(0xC0 | (val >> 6)));
            self.vec.insert(i + 1, (char)(0x80 | (val & 0x3F)));
        } else if (val < 0x10000) {
            self.vec.insert(i, (char)(0xE0 | (val >> 12)));
            self.vec.insert(i + 1, (char)(0x80 | ((val >> 6) & 0x3F)));
            self.vec.insert(i + 2, (char)(0x80 | (val & 0x3F)));
        } else {
            self.vec.insert(i, (char)(0xF0 | (val >> 18)));
            self.vec.insert(i + 1, (char)(0x80 | ((val >> 12) & 0x3F)));
            self.vec.insert(i + 2, (char)(0x80 | ((val >> 6) & 0x3F)));
            self.vec.insert(i + 3, (char)(0x80 | (val & 0x3F)));
        }
    }

    /// Removes and returns the rune at byte index `idx`.
    fn remove_rune_at(self, idx: usize) -> rune {
        let i: usize = 0;
        let count: usize = 0;
        let len = self.length();
        while i < len && count < idx {
            i = i + String::_utf8_seq_len(self.vec.get(i));
            count = count + 1;
        }
        
        if (i >= len) {
            return (rune)0;
        }
        
        let c = (byte)self.vec.get(i);
        let seq = String::_utf8_seq_len((char)c);
        let val: rune = 0;
        if (seq == 1) { val = (rune)c; }
        else if (seq == 2) { val = (rune)(((int)(c & 0x1F) << 6) | ((int)(byte)self.vec.get(i + 1) & 0x3F)); }
        else if (seq == 3) { val = (rune)(((int)(c & 0x0F) << 12) | (((int)(byte)self.vec.get(i + 1) & 0x3F) << 6) | ((int)(byte)self.vec.get(i + 2) & 0x3F)); }
        else if (seq == 4) { val = (rune)(((int)(c & 0x07) << 18) | (((int)(byte)self.vec.get(i + 1) & 0x3F) << 12) | (((int)(byte)self.vec.get(i + 2) & 0x3F) << 6) | ((int)(byte)self.vec.get(i + 3) & 0x3F)); }

        for (let j: usize = 0; j < seq; j = j + 1) {
            self.vec.remove(i);
        }
        return val;
    }

    /// Returns a substring of `num_chars` code points from `start_idx`.
    fn utf8_substr(self, start_idx: usize, num_chars: usize) -> String {
        if (num_chars == 0) { return String::new(""); }

        let byte_start: usize = 0;
        let byte_len: usize = 0;
        
        let count: usize = 0;
        let i: usize = 0;
        let len = self.length();
        let found_start = false;
        
        while i < len {
            // Check if we reached the start char
            if (!found_start && count == start_idx) {
                byte_start = i;
                found_start = true;
                // Reset count to track chars collected
                count = 0; 
            } else if (!found_start) {
                 // Still seeking start
                 let c = self.vec.get(i);
                 i = i + String::_utf8_seq_len(c);
                 count = count + 1;
                 continue;
            }
            
            // If we are here, we are collecting chars
            if (count < num_chars) {
                let c = self.vec.get(i);
                let seq = String::_utf8_seq_len(c);
                byte_len = byte_len + seq;
                i = i + seq;
                count = count + 1;
            } else {
                break;
            }
        }
        
        if (!found_start) { return String::new(""); }
        
        return self.substring(byte_start, byte_len);
    }
    /// Splits on the delimiter character into a Vec of substrings.
    fn split(self, delim: char) -> Vec<String> {
        let parts = Vec<String>::new();
        let len = self.length();
        if (len == 0) { return parts; }

        let start: usize = 0;
        let i: usize = 0;
        
        while i < len {
            if (self.vec.get(i) == delim) {
                // Found delimiter
                parts.push(self.substring(start, i - start));
                start = i + 1;
            }
            i = i + 1;
        }
        
        // Push last segment
        if (start <= len) {
            parts.push(self.substring(start, len - start));
        }
        
        return parts;
    }

    /// Returns a copy with leading/trailing whitespace removed.
    fn trim(self) -> String {
        let start: usize = 0;
        let len = self.length();
        let end = len;

        // Find start
        while (start < len) {
            let c = self.vec.get(start);
            if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
                break;
            }
            start = start + 1;
        }

        if (start == len) {
            return String::new("");
        }

        // Find end
        while (end > start) {
            let c = self.vec.get(end - 1);
            if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
                break;
            }
            end = end - 1;
        }

        return self.substring(start, end - start);
    }
    
    /// Returns a copy with all `target` replaced by `replacement`.
    fn replace(self, target: char*, replacement: char*) -> String {
        let t_len = strlen(target);
        if (t_len == 0) {
            return self.substring(0, self.length()); // clone
        }
        
        let s_len = self.length();
        let result = String::new("");
        
        let i: usize = 0;
        while (i < s_len) {
            // Check if match
            if (i + t_len <= s_len) {
                let is_match = true;
                // Manual strncmp against vec data
                for (let k: usize = 0; k < t_len; k = k + 1) {
                    if (self.vec.get(i + k) != target[k]) {
                        is_match = false;
                        break;
                    }
                }
                
                if (is_match) {
                    let r_str = String::new(replacement);
                    result.append(&r_str);
                    i = i + t_len;
                    continue;
                }
            }
            
            // Append single char
            let v = Vec<char>::new();
            v.push(self.vec.get(i));
            v.push(0);
            let ch_s = String::new(v.data);
            result.append(&ch_s);
            ch_s.free();
            i = i + 1;
        }
        return result;
    }

    // Parses the string as a decimal integer. Returns 0 when the string is
    // not a valid integer.
    /// Parses the string as a decimal integer (0 when invalid).
    fn to_int(self) -> int {
        let len = self.length();
        if (len == 0) { return 0; }

        let i: usize = 0;
        let neg = false;
        if (self.vec.get(0) == '-') {
            neg = true;
            i = 1;
        } else if (self.vec.get(0) == '+') {
            i = 1;
        }

        if (i >= len) { return 0; }

        let result: int = 0;
        while (i < len) {
            let c = self.vec.get(i);
            if (c < '0' || c > '9') { return 0; }
            result = result * 10 + (int)(c - '0');
            i = i + 1;
        }

        if (neg) { return -result; }
        return result;
    }

    // Returns a new string with this string repeated `count` times.
    /// Returns a copy repeated `count` times.
    fn repeated(self, count: usize) -> String {
        let len = self.length();
        let out = String::new("");
        if (count == 0 || len == 0) { return out; }
        out.reserve(len * count);
        for (let i: usize = 0; i < count; i = i + 1) {
            out.append(self);
        }
        return out;
    }

    // Returns a new string with the characters in reverse order.
    /// Returns a copy with the characters reversed.
    fn reverse(self) -> String {
        let len = self.length();
        let out = String::new("");
        if (len == 0) { return out; }
        out.reserve(len);
        let i = len;
        while (i > 0) {
            i = i - 1;
            let v = Vec<char>::new();
            v.push(self.vec.get(i));
            v.push(0);
            let ch_s = String::new(v.data);
            out.append(&ch_s);
            ch_s.free();
        }
        return out;
    }

    // Returns a copy with leading whitespace removed.
    /// Returns a copy with leading whitespace removed.
    fn trim_start(self) -> String {
        let len = self.length();
        let start: usize = 0;
        while (start < len) {
            let c = self.vec.get(start);
            if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
                break;
            }
            start = start + 1;
        }
        if (start == len) { return String::new(""); }
        return self.substring(start, len - start);
    }

    // Returns a copy with trailing whitespace removed.
    /// Returns a copy with trailing whitespace removed.
    fn trim_end(self) -> String {
        let len = self.length();
        let end = len;
        while (end > 0) {
            let c = self.vec.get(end - 1);
            if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
                break;
            }
            end = end - 1;
        }
        return self.substring(0, end);
    }
}