// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/12/String.jack

/**
 * Represents character strings. In addition for constructing and disposing
 * strings, the class features methods for getting and setting individual
 * characters of the string, for erasing the string's last character,
 * for appending a character to the string's end, and more typical
 * string-oriented operations.
 */
class String {

    field Array str;
    field int length;

    /** constructs a new empty string with a maximum length of maxLength
     *  and initial length of 0. */
    constructor String new(int maxLength) {
        if(maxLength > 0) {
            let str = Array.new(maxLength);
        } else {
            let str = 0;
        }
        let length = 0;
        return this;
    }

    /** Disposes this string. */
    method void dispose() {
        do Memory.deAlloc(this);
        return;
    }

    /** Returns the current length of this string. */
    method int length() {
        return length;
    }

    /** Returns the character at the j-th location of this string. */
    method char charAt(int j) {
        return str[j];
    }

    /** Sets the character at the j-th location of this string to c. */
    method void setCharAt(int j, char c) {
        let str[j] = c;
        return;
    }

    /** Appends c to this string's end and returns this string. */
    method String appendChar(char c) {
        let str[length] = c;
        let length = length + 1;
        return this;
    }

    /** Erases the last character from this string. */
    method void eraseLastChar() {
        let str[length - 1] = 0;
        let length = length - 1;
        return;
    }

    /** Returns the integer value of this string, 
     *  until a non-digit character is detected. */
    method int intValue() {
        var int val, i, d;
        var boolean neg;
        let i = 0;
        if(str[i] = 45) {
            let neg = true;
            let i = 1;
        }
        while(i < length) {
            let d = str[i] - 48;
            let val = val * 10 + d;
            let i = i + 1;
        }
        if(neg) {
            return -val;
        }
        return val;
    }

    function String int2String(int val) {
        var String string;
        var int lastDigit,  c;
        let string = String.new(64);
        let lastDigit = val - ((val / 10) * 10);
        let c = lastDigit + 48;
        if(val < 10) {
            do string.appendChar(c);
            return string;
        } else {
            do string.dispose();
            let string = String.int2String(val / 10);
            do string.appendChar(c);
            return string;
        }
    }

    /** Sets this string to hold a representation of the given value. */
    method void setInt(int val) {
        var String temp;
        var int i;
        let length = 0;
        if(val < 0) {
            do appendChar(45);
        }
        let i = 0;
        let temp = String.int2String(Math.abs(val));
        while(i < temp.length()) {
            do appendChar(temp.charAt(i));
            let i = i + 1;
        }
        do temp.dispose();
        return;
    }

    /** Returns the new line character. */
    function char newLine() {
        return 128;
    }

    /** Returns the backspace character. */
    function char backSpace() {
        return 129;
    }

    /** Returns the double quote (") character. */
    function char doubleQuote() {
        return 34;
    }
}
