204 lines
5.5 KiB
Plaintext
204 lines
5.5 KiB
Plaintext
// 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 int maxLength;
|
|
field int length;
|
|
field Array s;
|
|
|
|
/** constructs a new empty string with a maximum length of maxLength
|
|
* and initial length of 0. */
|
|
constructor String new(int maxStringLength) {
|
|
let maxLength = maxStringLength;
|
|
let length = 0;
|
|
// Only allocate memory for positive length.
|
|
if (maxLength > 0) {
|
|
let s = Array.new(maxLength);
|
|
} else {
|
|
let s = 0;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/** Disposes this string. */
|
|
method void dispose() {
|
|
// Only deAlloc for positive length. We do not alloc memory in constructor
|
|
// if length is not positive.
|
|
if (~(s = 0)) {
|
|
do s.dispose();
|
|
}
|
|
return;
|
|
}
|
|
|
|
/** Returns the current length of this string. */
|
|
method int length() {
|
|
return length;
|
|
}
|
|
|
|
/** Sets all fields to null and resets length. */
|
|
method void clear() {
|
|
var int i;
|
|
let i = 0;
|
|
|
|
while (i < maxLength) {
|
|
let s[i] = 0;
|
|
let i = i + 1;
|
|
}
|
|
let length = 0;
|
|
return;
|
|
}
|
|
|
|
/** Returns the character at the j-th location of this string. */
|
|
method char charAt(int j) {
|
|
if (j < maxLength) {
|
|
return s[j];
|
|
}
|
|
return 0; // Out-of-bounds access. Consider raising an error.
|
|
}
|
|
|
|
/** Sets the character at the j-th location of this string to c. */
|
|
method void setCharAt(int j, char c) {
|
|
if (j < maxLength) {
|
|
let s[j] = c;
|
|
} else {
|
|
// Out-of-bounds access. Consider raising an error.
|
|
}
|
|
return;
|
|
}
|
|
|
|
/** Appends c to this string's end and returns this string. */
|
|
method String appendChar(char c) {
|
|
if (length < maxLength) {
|
|
let s[length] = c;
|
|
let length = length + 1;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/** Erases the last character from this string. */
|
|
method void eraseLastChar() {
|
|
if (length > 0) {
|
|
let length = length - 1;
|
|
let s[length] = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/** Returns the integer value of this string,
|
|
* until a non-digit character is detected. */
|
|
method int intValue() {
|
|
var int i, result, multiplier;
|
|
var boolean isNegative, continue;
|
|
var char c;
|
|
let i = 0;
|
|
let isNegative = false;
|
|
|
|
if (charAt(0) = 45) {
|
|
let isNegative = true;
|
|
let i = i + 1;
|
|
}
|
|
|
|
// First iterate up to the highest numerical character.
|
|
let continue = true;
|
|
while (continue) {
|
|
let c = charAt(i);
|
|
if ((c > 47) & (c < 58)) {
|
|
let i = i + 1;
|
|
} else {
|
|
let continue = false;
|
|
}
|
|
if (~(i < maxLength)) {
|
|
let continue = false;
|
|
}
|
|
}
|
|
|
|
// Then iterate backwards and add the values to result.
|
|
// Checking if we are within the range allows us to not
|
|
// worry about a potential negative sign.
|
|
let continue = true;
|
|
let multiplier = 1;
|
|
let i = i - 1;
|
|
while (continue) {
|
|
let c = charAt(i);
|
|
if ((c > 47) & (c < 58)) {
|
|
let result = result + ((c - 48) * multiplier);
|
|
let multiplier = multiplier * 10;
|
|
} else {
|
|
let continue = false;
|
|
}
|
|
|
|
if (i = 0) {
|
|
let continue = false;
|
|
}
|
|
let i = i - 1;
|
|
}
|
|
|
|
if (isNegative) {
|
|
let result = -result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/** Sets this string to hold a representation of the given value. */
|
|
method void setInt(int val) {
|
|
var int digit, divisor;
|
|
var boolean firstDigitPrinted;
|
|
let divisor = 10000;
|
|
let firstDigitPrinted = false;
|
|
do clear();
|
|
|
|
if (val = 0) {
|
|
do appendChar(48); // 0
|
|
return;
|
|
}
|
|
|
|
if (val < 0) {
|
|
do appendChar(45); // 45 = '-'
|
|
let val = (~val) + 1;
|
|
}
|
|
|
|
while (~(divisor = 0)) {
|
|
let digit = val / divisor;
|
|
|
|
if (digit = 0) {
|
|
if (firstDigitPrinted) {
|
|
do appendChar(48 + 0);
|
|
}
|
|
} else {
|
|
do appendChar(48 + digit);
|
|
let firstDigitPrinted = true;
|
|
}
|
|
|
|
let val = val - (digit * divisor);
|
|
let divisor = divisor / 10;
|
|
}
|
|
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;
|
|
}
|
|
}
|