summaryrefslogtreecommitdiffstats
path: root/labb8/lib
diff options
context:
space:
mode:
Diffstat (limited to 'labb8/lib')
-rwxr-xr-xlabb8/lib/StanfordCPPLib/console.cpp164
-rwxr-xr-xlabb8/lib/StanfordCPPLib/console.h132
-rwxr-xr-xlabb8/lib/StanfordCPPLib/direction.cpp106
-rwxr-xr-xlabb8/lib/StanfordCPPLib/direction.h95
-rwxr-xr-xlabb8/lib/StanfordCPPLib/error.cpp42
-rwxr-xr-xlabb8/lib/StanfordCPPLib/error.h56
-rwxr-xr-xlabb8/lib/StanfordCPPLib/filelib.cpp360
-rwxr-xr-xlabb8/lib/StanfordCPPLib/filelib.h352
-rwxr-xr-xlabb8/lib/StanfordCPPLib/foreach.h217
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gevents.cpp335
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gevents.h734
-rwxr-xr-xlabb8/lib/StanfordCPPLib/ginteractors.cpp204
-rwxr-xr-xlabb8/lib/StanfordCPPLib/ginteractors.h370
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gmath.cpp50
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gmath.h104
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gobjects.cpp1033
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gobjects.h1491
-rwxr-xr-xlabb8/lib/StanfordCPPLib/graph.h836
-rwxr-xr-xlabb8/lib/StanfordCPPLib/grid.h516
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gtimer.cpp62
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gtimer.h116
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gtypes.cpp196
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gtypes.h301
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gwindow.cpp355
-rwxr-xr-xlabb8/lib/StanfordCPPLib/gwindow.h536
-rwxr-xr-xlabb8/lib/StanfordCPPLib/hashmap.cpp296
-rwxr-xr-xlabb8/lib/StanfordCPPLib/hashmap.h663
-rwxr-xr-xlabb8/lib/StanfordCPPLib/hashset.h613
-rwxr-xr-xlabb8/lib/StanfordCPPLib/lexicon.cpp316
-rwxr-xr-xlabb8/lib/StanfordCPPLib/lexicon.h366
-rwxr-xr-xlabb8/lib/StanfordCPPLib/main.cpp108
-rwxr-xr-xlabb8/lib/StanfordCPPLib/map.h910
-rwxr-xr-xlabb8/lib/StanfordCPPLib/platform.cpp1417
-rwxr-xr-xlabb8/lib/StanfordCPPLib/platform.h134
-rwxr-xr-xlabb8/lib/StanfordCPPLib/point.cpp44
-rwxr-xr-xlabb8/lib/StanfordCPPLib/point.h113
-rwxr-xr-xlabb8/lib/StanfordCPPLib/pqueue.h400
-rwxr-xr-xlabb8/lib/StanfordCPPLib/private/main.h58
-rwxr-xr-xlabb8/lib/StanfordCPPLib/private/randompatch.h63
-rwxr-xr-xlabb8/lib/StanfordCPPLib/private/tokenpatch.h11
-rwxr-xr-xlabb8/lib/StanfordCPPLib/private/tplatform.h25
-rwxr-xr-xlabb8/lib/StanfordCPPLib/queue.h372
-rwxr-xr-xlabb8/lib/StanfordCPPLib/random.cpp99
-rwxr-xr-xlabb8/lib/StanfordCPPLib/random.h58
-rwxr-xr-xlabb8/lib/StanfordCPPLib/set.h621
-rwxr-xr-xlabb8/lib/StanfordCPPLib/simpio.cpp67
-rwxr-xr-xlabb8/lib/StanfordCPPLib/simpio.h53
-rwxr-xr-xlabb8/lib/StanfordCPPLib/sound.cpp31
-rwxr-xr-xlabb8/lib/StanfordCPPLib/sound.h63
-rwxr-xr-xlabb8/lib/StanfordCPPLib/stack.h285
-rwxr-xr-xlabb8/lib/StanfordCPPLib/startup.cpp34
-rwxr-xr-xlabb8/lib/StanfordCPPLib/strlib.cpp252
-rwxr-xr-xlabb8/lib/StanfordCPPLib/strlib.h222
-rwxr-xr-xlabb8/lib/StanfordCPPLib/tokenscanner.cpp411
-rwxr-xr-xlabb8/lib/StanfordCPPLib/tokenscanner.h351
-rwxr-xr-xlabb8/lib/StanfordCPPLib/vector.h727
-rwxr-xr-xlabb8/lib/readme.txt4
-rwxr-xr-xlabb8/lib/spl.jarbin0 -> 402510 bytes
58 files changed, 17950 insertions, 0 deletions
diff --git a/labb8/lib/StanfordCPPLib/console.cpp b/labb8/lib/StanfordCPPLib/console.cpp
new file mode 100755
index 0000000..c55564c
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/console.cpp
@@ -0,0 +1,164 @@
+/*
+ * File: console.cpp
+ * -----------------
+ * This file implements the console.h interface.
+ */
+
+#include <string>
+#include "console.h"
+#include "error.h"
+#include "platform.h"
+using namespace std;
+
+static void sclTerminateHandler();
+
+static Platform *pp = getPlatform();
+static bool consoleEcho = false;
+static bool consolePrintExceptions = false;
+static string consoleLogFile = "";
+static void (*old_terminate)() = NULL;
+
+void clearConsole() {
+ pp->clearConsole();
+}
+
+bool getConsoleEcho() {
+ return consoleEcho;
+}
+
+string getConsoleLogFile() {
+ return consoleLogFile;
+}
+
+bool getConsolePrintExceptions() {
+ return consolePrintExceptions;
+}
+
+void setConsoleEcho(bool echo) {
+ consoleEcho = echo;
+}
+
+void setConsoleFont(const string & font) {
+ pp->setConsoleFont(font);
+}
+
+void setConsoleLogFile(const string & filename) {
+ consoleLogFile = filename;
+}
+
+void setConsolePrintExceptions(bool printExceptions) {
+ if (printExceptions && !consolePrintExceptions) {
+ old_terminate = set_terminate(sclTerminateHandler);
+ } else if (!printExceptions && consolePrintExceptions) {
+ set_terminate(old_terminate);
+ }
+ consolePrintExceptions = printExceptions;
+}
+
+void setConsoleSize(double width, double height) {
+ pp->setConsoleSize(width, height);
+}
+
+static void sclTerminateHandler() {
+ ostream& out = cerr;
+ try {
+ throw; // re-throws the exception that already occurred
+ } catch (const ErrorException& ex) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** An ErrorException occurred during program execution: \n";
+ msg += " *** ";
+ msg += ex.what();
+ msg += "\n ***\n\n";
+ cout.flush();
+ out << msg;
+ throw ex;
+ } catch (const std::exception& ex) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** An exception occurred during program execution: \n";
+ msg += " *** ";
+ msg += ex.what();
+ msg += "\n ***\n\n";
+ cout.flush();
+ out << msg;
+ throw ex;
+ } catch (std::string str) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A string exception occurred during program execution: \n";
+ msg += " *** \"";
+ msg += str;
+ msg += "\"\n ***\n";
+ cout.flush();
+ out << msg;
+ throw str;
+ } catch (char const* str) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A string exception occurred during program execution: \n";
+ msg += " *** \"";
+ msg += str;
+ msg += "\"\n ***\n";
+ cout.flush();
+ out << msg;
+ throw str;
+ } catch (int n) {
+ char buf[128];
+ snprintf(buf, 128, "%d", n);
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** An int exception occurred during program execution: \n";
+ msg += " *** ";
+ msg += buf;
+ msg += "\n ***\n\n";
+ cout.flush();
+ out << msg;
+ throw n;
+ } catch (long l) {
+ char buf[128];
+ snprintf(buf, 128, "%ld", l);
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A long exception occurred during program execution: \n";
+ msg += " *** ";
+ msg += buf;
+ msg += "\n ***\n\n";
+ cout.flush();
+ out << msg;
+ throw l;
+ } catch (char c) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A char exception occurred during program execution: \n";
+ msg += " *** '";
+ msg += c;
+ msg += "'\n ***\n";
+ cout.flush();
+ out << msg;
+ throw c;
+ } catch (bool b) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A bool exception occurred during program execution: \n";
+ msg += " *** ";
+ msg += (b ? "true" : "false");
+ msg += "\n ***\n\n";
+ cout.flush();
+ out << msg;
+ throw b;
+ } catch (double d) {
+ char buf[128];
+ snprintf(buf, 128, "%lf", d);
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A double exception occurred during program execution: \n";
+ msg += " *** ";
+ msg += buf;
+ msg += "\n ***\n\n";
+ cout.flush();
+ out << msg;
+ throw d;
+ }
+ abort();
+}
diff --git a/labb8/lib/StanfordCPPLib/console.h b/labb8/lib/StanfordCPPLib/console.h
new file mode 100755
index 0000000..dd3d863
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/console.h
@@ -0,0 +1,132 @@
+/*
+ * File: console.h
+ * ---------------
+ * This file redirects the <code>cin</code>, <code>cout</code>,
+ * and <code>cerr</code> channels to use a console window. This file
+ * must be included in the source file that contains the <code>main</code>
+ * method, although it may be included in other source files as well.
+ */
+
+#ifndef _console_h
+#define _console_h
+
+#include <string>
+
+/*
+ * Function: clearConsole
+ * Usage: clearConsole();
+ * ----------------------
+ * Erases the contents of the console window.
+ */
+
+void clearConsole();
+
+/*
+ * Function: getConsoleEcho
+ * Usage: bool echo = getConsoleEcho();
+ * ----------------------------
+ * Returns whether or not the input/output from the Stanford graphical
+ * console window is being echoed onto the standard operating system terminal
+ * window. Initially this is false unless set to true by a previous call to
+ * setConsoleEcho(true).
+ */
+
+bool getConsoleEcho();
+
+/*
+ * Function: getConsoleLogFile
+ * Usage: string consoleLogFile = getConsoleLogFile();
+ * ----------------------------
+ * Returns the file name, if any, that was set by a previous call to
+ * setConsoleLogFile into which console in/output is being logged.
+ * If setConsoleLogFile has not been called yet by this program, returns
+ * an empty string ("").
+ */
+
+std::string getConsoleLogFile();
+
+/*
+ * Function: getConsolePrintExceptions
+ * Usage: bool ex = getConsolePrintExceptions();
+ * ----------------------------
+ * Returns whether or not a feature is enabled that causes exceptions to be
+ * echoed to the Stanford graphical console window when they are thrown.
+ * Disabled (false) by default.
+ */
+
+bool getConsolePrintExceptions();
+
+/*
+ * Function: setConsoleEcho
+ * Usage: setConsoleEcho(true);
+ * ----------------------------
+ * Enables or disables echoing the input/output from the Stanford graphical
+ * console window onto the standard operating system terminal window.
+ * Normally you don't need this echoing, but if you want to be able to copy
+ * and paste your console interaction into another window, it is useful.
+ */
+
+void setConsoleEcho(bool echo);
+
+/*
+ * Function: setConsoleFont
+ * Usage: setConsoleFont(font);
+ * ----------------------------
+ * Changes the font used for the console. The <code>font</code> parameter
+ * is typically a string in the form <code>family-style-size</code>.
+ * In this string, <code>family</code> is the name of the font family;
+ * <code>style</code> is either missing (indicating a plain font) or one
+ * of the strings <code>Bold</code>, <code>Italic</code>, or
+ * <code>BoldItalic</code>; and <code>size</code> is an integer
+ * indicating the point size. If any of these components is
+ * specified as an asterisk, the existing value is retained.
+ * The <code>font</code> parameter can also be a sequence of
+ * such specifications separated by semicolons, in which case the
+ * first available font on the system is used.
+ */
+
+void setConsoleFont(const std::string & font);
+
+/*
+ * Function: setConsoleLog
+ * Usage: setConsoleLog("myoutput.txt");
+ * ----------------------------
+ * Begins dumping a copy of all future console in/output to the given file name.
+ * Useful for capturing output logs and writing auto-grader scripts.
+ * If you are logging to a file, the output still also appears on the console.
+ * By default, logging is not initially enabled.
+ * Log text is appended to any existing content in the file as it is printed.
+ * If you pass the name of an invalid file, or one that the current user does
+ * not have permission to write, a file I/O error will occur the next time
+ * your program performs a console I/O operation to cout or cin.
+ * Set to an empty string ("") to disable logging.
+ */
+
+void setConsoleLogFile(const std::string & filename);
+
+/*
+ * Function: setConsolePrintExceptions
+ * Usage: setConsolePrintExceptions(true);
+ * ----------------------------
+ * Enables or disables a feature that causes exceptions to be echoed to the
+ * Stanford graphical console window when they are thrown.
+ * Disabled (false) by default.
+ * Note that using this feature may make it harder to get a stack trace in the
+ * debugger if you are debugging the cause of an exception.
+ */
+
+void setConsolePrintExceptions(bool printExceptions);
+
+/*
+ * Function: setConsoleSize
+ * Usage: setConsoleSize(width, height);
+ * -------------------------------------
+ * Changes the size of the console to the specified dimensions, measured
+ * in pixels.
+ */
+
+void setConsoleSize(double width, double height);
+
+#include "private/main.h"
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/direction.cpp b/labb8/lib/StanfordCPPLib/direction.cpp
new file mode 100755
index 0000000..4156d56
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/direction.cpp
@@ -0,0 +1,106 @@
+/*
+ * File: direction.cpp
+ * -------------------
+ * This file implements the direction.h interface.
+ */
+
+#include "direction.h"
+#include "error.h"
+#include "strlib.h"
+#include "tokenscanner.h"
+using namespace std;
+
+/*
+ * Implementation notes: leftFrom, rightFrom, opposite
+ * ---------------------------------------------------
+ * These functions use the remainder operator to cycle through the
+ * internal values of the enumeration type. Note that the leftFrom
+ * function cannot subtract 1 from the direction because the result
+ * might then be negative; adding 3 achieves the same effect but
+ * ensures that the values remain positive.
+ */
+
+Direction leftFrom(Direction dir) {
+ return Direction((dir + 3) % 4);
+}
+
+Direction rightFrom(Direction dir) {
+ return Direction((dir + 1) % 4);
+}
+
+Direction opposite(Direction dir) {
+ return Direction((dir + 2) % 4);
+}
+
+/*
+ * Implementation notes: directionToString
+ * ---------------------------------------
+ * The C++ compiler requires the default clause to ensure that this
+ * function always returns a string, even if the direction is not one
+ * of the legal values.
+ */
+
+string directionToString(Direction dir) {
+ switch (dir) {
+ case NORTH: return "NORTH";
+ case EAST: return "EAST";
+ case SOUTH: return "SOUTH";
+ case WEST: return "WEST";
+ default: return "???";
+ }
+}
+
+/*
+ * Implementation notes: <<
+ * ------------------------
+ * This operator must return the stream by reference after printing
+ * the value. The operator << returns this stream, so the function
+ * can be implemented as a single line.
+ */
+
+std::ostream & operator<<(std::ostream & os, const Direction & dir) {
+ return os << directionToString(dir);
+}
+
+/*
+ * Implementation notes: >>
+ * ------------------------
+ * This implementation uses the TokenScanner to read tokens from the
+ * stream.
+ */
+
+std::istream & operator>>(std::istream & is, Direction & dir) {
+ TokenScanner scanner(is);
+ scanner.ignoreWhitespace();
+ string token = toUpperCase(scanner.nextToken());
+ if (token == "") {
+ dir = Direction(-1);
+ } else if (startsWith("NORTH", token)) {
+ dir = NORTH;
+ } else if (startsWith("EAST", token)) {
+ dir = EAST;
+ } else if (startsWith("SOUTH", token)) {
+ dir = SOUTH;
+ } else if (startsWith("WEST", token)) {
+ dir = WEST;
+ } else {
+ error("Direction: Unrecognized direction " + token);
+ }
+ return is;
+}
+
+/*
+ * Implementation notes: ++
+ * ------------------------
+ * The int parameter in the signature for this operator is a marker used
+ * by the C++ compiler to identify the suffix form of the operator. Note
+ * that the value after incrementing a variable containing WEST will be
+ * out of the Direction range. That fact will not cause a problem if
+ * this operator is used only in the for loop idiom for which it is defined.
+ */
+
+Direction operator++(Direction & dir, int) {
+ Direction old = dir;
+ dir = Direction(dir + 1);
+ return old;
+}
diff --git a/labb8/lib/StanfordCPPLib/direction.h b/labb8/lib/StanfordCPPLib/direction.h
new file mode 100755
index 0000000..d858aca
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/direction.h
@@ -0,0 +1,95 @@
+/*
+ * File: direction.h
+ * -----------------
+ * This file exports an enumerated type called <code>Direction</code>
+ * whose elements are the four compass points: <code>NORTH</code>,
+ * <code>EAST</code>, <code>SOUTH</code>, and <code>WEST</code>.
+ */
+
+#ifndef _direction_h
+#define _direction_h
+
+#include <iostream>
+#include <string>
+#include "foreach.h"
+
+/*
+ * Type: Direction
+ * ---------------
+ * This enumerated type is used to represent the four compass directions.
+ */
+
+enum Direction { NORTH, EAST, SOUTH, WEST };
+
+/*
+ * Function: leftFrom
+ * Usage: Direction newdir = leftFrom(dir);
+ * ----------------------------------------
+ * Returns the direction that is to the left of the argument.
+ */
+
+Direction leftFrom(Direction dir);
+
+/*
+ * Function: rightFrom
+ * Usage: Direction newdir = rightFrom(dir);
+ * -----------------------------------------
+ * Returns the direction that is to the right of the argument.
+ */
+
+Direction rightFrom(Direction dir);
+
+/*
+ * Function: opposite
+ * Usage: Direction newdir = opposite(dir);
+ * ----------------------------------------
+ * Returns the direction that is opposite to the argument.
+ */
+
+Direction opposite(Direction dir);
+
+/*
+ * Function: directionToString
+ * Usage: string str = directionToString(dir);
+ * -------------------------------------------
+ * Returns the name of the direction as a string.
+ */
+
+std::string directionToString(Direction dir);
+
+/*
+ * Operator: <<
+ * Usage: os << dir;
+ * -----------------
+ * Overloads the <code>&lt;&lt;</code> operator so that it is able
+ * to display <code>Direction</code> values.
+ */
+
+std::ostream & operator<<(std::ostream & os, const Direction & dir);
+
+/*
+ * Operator: >>
+ * Usage: is >> dir;
+ * -----------------
+ * Overloads the <code>&gt;&gt;</code> operator so that it is able
+ * to read <code>Direction</code> values.
+ */
+
+std::istream & operator>>(std::istream & os, Direction & dir);
+
+/*
+ * Operator: ++
+ * Usage: dir++
+ * ------------
+ * Overloads the suffix version of the <code>++</code> operator to
+ * work with <code>Direction</code> values. The sole purpose of this
+ * definition is to support the idiom
+ *
+ *<pre>
+ * for (Direction dir = NORTH; dir &lt;= WEST; dir++) ...
+ *</pre>
+ */
+
+Direction operator++(Direction & dir, int);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/error.cpp b/labb8/lib/StanfordCPPLib/error.cpp
new file mode 100755
index 0000000..c0e0a36
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/error.cpp
@@ -0,0 +1,42 @@
+/*
+ * File: error.cpp
+ * ---------------
+ * Implementation of the error function.
+ */
+
+#include <exception>
+#include <string>
+#include <iostream>
+#include "error.h"
+using namespace std;
+
+/* Definitions for the ErrorException class */
+
+ErrorException::ErrorException(string msg) {
+ this->msg = msg;
+}
+
+ErrorException::~ErrorException() throw () {
+ /* Empty */
+}
+
+string ErrorException::getMessage() const {
+ return msg;
+}
+
+const char *ErrorException::what() const throw () {
+ return ("Error: " + msg).c_str();
+}
+
+/*
+ * Implementation notes: error
+ * ---------------------------
+ * Earlier implementations of error made it possible, at least on the
+ * Macintosh, to help the debugger generate a backtrace at the point
+ * of the error. Unfortunately, doing so is no longer possible if
+ * the errors are catchable.
+ */
+
+void error(string msg) {
+ throw ErrorException(msg);
+}
diff --git a/labb8/lib/StanfordCPPLib/error.h b/labb8/lib/StanfordCPPLib/error.h
new file mode 100755
index 0000000..359ea99
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/error.h
@@ -0,0 +1,56 @@
+/*
+ * File: error.h
+ * -------------
+ * This file defines the <code>ErrorException</code> class and the
+ * <code>error</code> function.
+ */
+
+#ifndef _error_h
+#define _error_h
+
+#include <string>
+#include <exception>
+
+/*
+ * Class: ErrorException
+ * ---------------------
+ * This exception is thrown by calls to the <code>error</code>
+ * function. Typical code for catching errors looks like this:
+ *
+ *<pre>
+ * try {
+ * ... code in which an error might occur ...
+ * } catch (ErrorException & ex) {
+ * ... code to handle the error condition ...
+ * }
+ *</pre>
+ *
+ * If an <code>ErrorException</code> is thrown at any point in the
+ * range of the <code>try</code> (including in functions called from
+ * that code), control will jump immediately to the error handler.
+ */
+
+class ErrorException : public std::exception {
+public:
+ ErrorException(std::string msg);
+ virtual ~ErrorException() throw ();
+ virtual std::string getMessage() const;
+ virtual const char *what() const throw ();
+
+private:
+ std::string msg;
+};
+
+/*
+ * Function: error
+ * Usage: error(msg);
+ * ------------------
+ * Signals an error condition in a program by throwing an
+ * <code>ErrorException</code> with the specified message.
+ */
+
+void error(std::string msg);
+
+#include "private/main.h"
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/filelib.cpp b/labb8/lib/StanfordCPPLib/filelib.cpp
new file mode 100755
index 0000000..c598db4
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/filelib.cpp
@@ -0,0 +1,360 @@
+/*
+ * File: filelib.cpp
+ * -----------------
+ * This file implements the filelib.h interface. All platform dependencies
+ * are managed through the platform interface.
+ */
+
+#include <algorithm>
+#include <cctype>
+#include <cstdio>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include "filelib.h"
+#include "foreach.h"
+#include "platform.h"
+#include "strlib.h"
+#include "vector.h"
+using namespace std;
+
+static Platform *pp = getPlatform();
+
+/* Prototypes */
+
+static void splitPath(string path, Vector<string> list);
+static bool recursiveMatch(string str, int sx, string pattern, int px);
+
+/* Implementations */
+
+bool openFile(ifstream & stream, string filename) {
+ stream.clear();
+ stream.open(expandPathname(filename).c_str());
+ return !stream.fail();
+}
+
+bool openFile(ofstream & stream, string filename) {
+ stream.clear();
+ stream.open(expandPathname(filename).c_str());
+ return !stream.fail();
+}
+
+string promptUserForFile(ifstream & stream, string prompt) {
+ while (true) {
+ cout << prompt;
+ string filename;
+ getline(cin, filename);
+ openFile(stream, filename);
+ if (!stream.fail()) return filename;
+ stream.clear();
+ cout << "Unable to open that file. Try again." << endl;
+ if (prompt == "") prompt = "Input file: ";
+ }
+}
+
+string promptUserForFile(ofstream & stream, string prompt) {
+ while (true) {
+ cout << prompt;
+ string filename;
+ getline(cin, filename);
+ openFile(stream, filename);
+ if (!stream.fail()) return filename;
+ stream.clear();
+ cout << "Unable to open that file. Try again." << endl;
+ if (prompt == "") prompt = "Output file: ";
+ }
+}
+
+string openFileDialog(ifstream & stream) {
+ return openFileDialog(stream, "Open File", "");
+}
+
+string openFileDialog(ifstream & stream, string title) {
+ return openFileDialog(stream, title, "");
+}
+
+string openFileDialog(ifstream & stream, string title, string path) {
+ string filename = pp->openFileDialog(title, "load", path);
+ if (filename == "") return "";
+ stream.open(filename.c_str());
+ return (stream.fail()) ? "" : filename;
+}
+
+string openFileDialog(ofstream & stream) {
+ return openFileDialog(stream, "Open File", "");
+}
+
+string openFileDialog(ofstream & stream, string title) {
+ return openFileDialog(stream, title, "");
+}
+
+string openFileDialog(ofstream & stream, string title, string path) {
+ string filename = pp->openFileDialog(title, "save", path);
+ if (filename == "") return "";
+ stream.open(filename.c_str());
+ return (stream.fail()) ? "" : filename;
+}
+
+void readEntireFile(istream & is, Vector<string> & lines) {
+ lines.clear();
+ while (true) {
+ string line;
+ getline(is, line);
+ if (is.fail()) break;
+ lines.add(line);
+ }
+}
+
+void readEntireFile(istream & is, vector<string> & lines) {
+ lines.clear();
+ while (true) {
+ string line;
+ getline(is, line);
+ if (is.fail()) break;
+ lines.push_back(line);
+ }
+}
+
+string getRoot(string filename) {
+ int dot = -1;
+ int len = filename.length();
+ for (int i = 0; i < len; i++) {
+ char ch = filename[i];
+ if (ch == '.') dot = i;
+ if (ch == '/' || ch == '\\') dot = -1;
+ }
+ if (dot == -1) {
+ return filename;
+ } else {
+ return filename.substr(0, dot);
+ }
+}
+
+string getExtension(string filename) {
+ int dot = -1;
+ int len = filename.length();
+ for (int i = 0; i < len; i++) {
+ char ch = filename[i];
+ if (ch == '.') dot = i;
+ if (ch == '/' || ch == '\\') dot = -1;
+ }
+ if (dot == -1) {
+ return "";
+ } else {
+ return filename.substr(dot);
+ }
+}
+
+string getHead(string filename) {
+ int slash = -1;
+ int len = filename.length();
+ for (int i = 0; i < len; i++) {
+ char ch = filename[i];
+ if (ch == '/' || ch == '\\') slash = i;
+ }
+ if (slash < 0) {
+ return "";
+ } else if (slash == 0) {
+ return "/";
+ } else {
+ return filename.substr(0, slash);
+ }
+}
+
+string getTail(string filename) {
+ int slash = -1;
+ int len = filename.length();
+ for (int i = 0; i < len; i++) {
+ char ch = filename[i];
+ if (ch == '/' || ch == '\\') slash = i;
+ }
+ if (slash < 0) {
+ return filename;
+ } else {
+ return filename.substr(slash + 1);
+ }
+}
+
+string defaultExtension(string filename, string ext) {
+ bool force = (ext[0] == '*');
+ if (force) ext = ext.substr(1);
+ int dot = -1;
+ int len = filename.length();
+ for (int i = 0; i < len; i++) {
+ char ch = filename[i];
+ if (ch == '.') dot = i;
+ if (ch == '/' || ch == '\\') dot = -1;
+ }
+ if (dot == -1) {
+ force = true;
+ dot = len;
+ }
+ if (force) {
+ return filename.substr(0, dot) + ext;
+ } else {
+ return filename;
+ }
+}
+
+string openOnPath(ifstream & stream, string path, string filename) {
+ Vector<string> paths;
+ splitPath(path, paths);
+ foreach (string dir in paths) {
+ string pathname = dir + "/" + filename;
+ if (openFile(stream, pathname)) return pathname;
+ }
+ return "";
+}
+
+string openOnPath(ofstream & stream, string path, string filename) {
+ Vector<string> paths;
+ splitPath(path, paths);
+ foreach (string dir in paths) {
+ string pathname = dir + "/" + filename;
+ if (openFile(stream, pathname)) return pathname;
+ }
+ return "";
+}
+
+string findOnPath(string path, string filename) {
+ ifstream stream;
+ string result = openOnPath(stream, path, filename);
+ if (result != "") stream.close();
+ return result;
+}
+
+void deleteFile(string filename) {
+ remove(expandPathname(filename).c_str());
+}
+
+void renameFile(string oldname, string newname) {
+ oldname = expandPathname(oldname);
+ newname = expandPathname(newname);
+ rename(oldname.c_str(), newname.c_str());
+}
+
+void createDirectoryPath(string path) {
+ size_t cp = 1;
+ if (path == "") return;
+ while ((cp = path.find('/', cp + 1)) != string::npos) {
+ createDirectory(path.substr(0, cp - 1));
+ }
+ createDirectory(path);
+}
+
+bool matchFilenamePattern(string filename, string pattern) {
+ return recursiveMatch(filename, 0, pattern, 0);
+}
+
+bool fileExists(string filename) {
+ return pp->fileExists(filename);
+}
+
+bool isFile(string filename) {
+ return pp->isFile(filename);
+}
+
+bool isSymbolicLink(string filename) {
+ return pp->isSymbolicLink(filename);
+}
+
+bool isDirectory(string filename) {
+ return pp->isDirectory(filename);
+}
+
+void setCurrentDirectory(string path) {
+ return pp->setCurrentDirectory(path);
+}
+
+string getCurrentDirectory() {
+ return pp->getCurrentDirectory();
+}
+
+void createDirectory(string path) {
+ return pp->createDirectory(path);
+}
+
+string getDirectoryPathSeparator() {
+ return pp->getDirectoryPathSeparator();
+}
+
+string getSearchPathSeparator() {
+ return pp->getSearchPathSeparator();
+}
+
+string expandPathname(string filename) {
+ return pp->expandPathname(filename);
+}
+
+void listDirectory(string path, Vector<string> & list) {
+ vector<string> vec;
+ listDirectory(path, vec);
+ list.clear();
+ foreach (string file in vec) {
+ list.add(file);
+ }
+}
+
+void listDirectory(string path, vector<string> & list) {
+ return pp->listDirectory(path, list);
+}
+
+/* Private functions */
+
+static void splitPath(string path, Vector<string> list) {
+ char sep = (path.find(';') == string::npos) ? ':' : ';';
+ path += sep;
+ size_t start = 0;
+ while (true) {
+ size_t finish = path.find(sep, start);
+ if (finish == string::npos) break;
+ if (finish > start + 1) {
+ list.add(path.substr(start, finish - start - 1));
+ }
+ start = finish + 1;
+ }
+}
+
+static bool recursiveMatch(string str, int sx, string pattern, int px) {
+ int slen = str.length();
+ int plen = pattern.length();
+ if (px == plen) return (sx == slen);
+ char pch = pattern[px];
+ if (pch == '*') {
+ for (int i = sx; i <= slen; i++) {
+ if (recursiveMatch(str, i, pattern, px + 1)) return true;
+ }
+ return false;
+ }
+ if (sx == slen) return false;
+ char sch = str[sx];
+ if (pch == '[') {
+ bool match = false;
+ bool invert = false;
+ px++;
+ if (px == plen) {
+ error("matchFilenamePattern: missing ]");
+ }
+ if (pattern[px] == '^') {
+ px++;
+ invert = true;
+ }
+ while (px < plen && pattern[px] != ']') {
+ if (px + 2 < plen && pattern[px + 1] == '-') {
+ match |= (sch >= pattern[px] && sch <= pattern[px + 2]);
+ px += 3;
+ } else {
+ match |= (sch == pattern[px]);
+ px++;
+ }
+ }
+ if (px == plen) {
+ error("matchFilenamePattern: missing ]");
+ }
+ if (match == invert) return false;
+ } else if (pch != '?') {
+ if (pch != sch) return false;
+ }
+ return recursiveMatch(str, sx + 1, pattern, px + 1);
+}
diff --git a/labb8/lib/StanfordCPPLib/filelib.h b/labb8/lib/StanfordCPPLib/filelib.h
new file mode 100755
index 0000000..f0c90ea
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/filelib.h
@@ -0,0 +1,352 @@
+/*
+ * File: filelib.h
+ * ---------------
+ * This file exports a standardized set of tools for working with
+ * files. The library offers at least some portability across the
+ * file systems used in the three supported platforms: Mac OSX,
+ * Windows, and Linux. Directory and search paths are allowed to
+ * contain separators in any of the supported styles, which usually
+ * makes it possible to use the same code on different platforms.
+ */
+
+#ifndef _filelib_h
+#define _filelib_h
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include "vector.h"
+
+/*
+ * Function: openFile
+ * Usage: if (openFile(stream, filename)) ...
+ * ------------------------------------------
+ * Opens the filestream <code>stream</code> using the specified
+ * filename. This function is similar to the <code>open</code>
+ * method of the stream classes, but uses a C++ <code>string</code>
+ * object instead of the older C-style string. If the operation
+ * succeeds, <code>openFile</code> returns <code>true</code>;
+ * if it fails, <code>openFile</code> sets the failure flag in the
+ * stream and returns <code>false</code>.
+ */
+
+bool openFile(std::ifstream & stream, std::string filename);
+bool openFile(std::ofstream & stream, std::string filename);
+
+/*
+ * Function: promptUserForFile
+ * Usage: string filename = promptUserForFile(stream, prompt);
+ * -----------------------------------------------------------
+ * Asks the user for the name of a file. The file is opened using
+ * the reference parameter <code>stream</code>, and the function
+ * returns the name of the file. If the requested file cannot be
+ * opened, the user is given additional chances to enter a valid file.
+ * The optional <code>prompt</code> argument provides an input prompt
+ * for the user.
+ */
+
+std::string promptUserForFile(std::ifstream & stream, std::string prompt = "");
+std::string promptUserForFile(std::ofstream & stream, std::string prompt = "");
+
+/*
+ * Function: openFileDialog
+ * Usage: string filename = openFileDialog(stream);
+ * string filename = openFileDialog(stream, title);
+ * string filename = openFileDialog(stream, title, path);
+ * -------------------------------------------------------------
+ * Opens a dialog that allows the user to choose the file. The
+ * <code>title</code> parameter is displayed in the dialog title.
+ * The <code>path</code> parameter is used to set the working directory;
+ * if <code>path</code> does not appear, <code>openFileDialog</code>
+ * uses the current directory.
+ */
+
+std::string openFileDialog(std::ifstream & stream);
+std::string openFileDialog(std::ifstream & stream, std::string title);
+std::string openFileDialog(std::ifstream & stream, std::string title,
+ std::string path);
+std::string openFileDialog(std::ofstream & stream);
+std::string openFileDialog(std::ofstream & stream, std::string title);
+std::string openFileDialog(std::ofstream & stream, std::string title,
+ std::string path);
+
+/*
+ * Function: readEntireFile
+ * Usage: readEntireFile(is, lines);
+ * ---------------------------------
+ * Reads the entire contents of the specified input stream into the
+ * string vector <code>lines</code>. The client is responsible for
+ * opening and closing the stream. The vector can be either an STL
+ * <code>vector</code> or a <code>Vector</code> as defined in the
+ * Stanford C++ libraries.
+ */
+
+void readEntireFile(std::istream & is, Vector<std::string> & lines);
+void readEntireFile(std::istream & is, std::vector<std::string> & lines);
+
+/*
+ * Function: getRoot
+ * Usage: string root = getRoot(filename);
+ * ---------------------------------------
+ * Returns the root of <code>filename</code>. The root consists
+ * of everything in <code>filename</code> up to the last dot and
+ * the subsequent extension. If no dot appears in the final component
+ * of the filename, <code>getRoot</code> returns the entire name.
+ */
+
+std::string getRoot(std::string filename);
+
+/*
+ * Function: getExtension
+ * Usage: ext = getExtension(filename);
+ * ------------------------------------
+ * Returns the extension of <code>filename</code>. The extension
+ * consists of the separating dot and all subsequent characters.
+ * If no dot exists in the final component, <code>getExtension</code>
+ * returns the empty string. These semantics ensure that concatenating
+ * the root and the extension always returns the original filename.
+ */
+
+std::string getExtension(std::string filename);
+
+/*
+ * Function: getHead
+ * Usage: head = getHead(filename);
+ * --------------------------------
+ * Returns all but the last component of a path name. The components
+ * of the path name can be separated by any of the directory path
+ * separators (forward or reverse slashes). The special cases are
+ * illustrated by the following examples:
+ *
+ *<pre>
+ * getHead("a/b") = "a" getTail("a/b") = "b"
+ * getHead("a") = "" getTail("a") = "a"
+ * getHead("/a") = "/" getTail("/a") = "a"
+ * getHead("/") = "/" getTail("/") = ""
+ *</pre>
+ */
+
+std::string getHead(std::string filename);
+
+/*
+ * Function: getTail
+ * Usage: tail = getTail(filename);
+ * --------------------------------
+ * Returns the last component of a path name. The components of the
+ * path name can be separated by any of the directory path separators
+ * (forward or reverse slashes). For details on the interpretation of
+ * special cases, see the comments for the <code>getHead</code> function.
+ */
+
+std::string getTail(std::string filename);
+
+/*
+ * Function: defaultExtension
+ * Usage: string newname = defaultExtension(filename, ext);
+ * --------------------------------------------------------
+ * Adds an extension to a file name if none already exists. If the
+ * <code>extension</code> argument begins with a leading <code>*</code>,
+ * any existing extension in <code>filename</code> is replaced by
+ * <code>ext</code>.
+ */
+
+std::string defaultExtension(std::string filename, std::string ext);
+
+/*
+ * Function: openOnPath
+ * Usage: string pathname = openOnPath(stream, path, filename);
+ * ------------------------------------------------------------
+ * Opens a file using a search path. If <code>openOnPath</code>
+ * is successful, it returns the first path name on the search path
+ * for which <code>stream.open</code> succeeds. The <code>path</code>
+ * argument consists of a list of directories that are prepended to the
+ * filename, unless <code>filename</code> begins with an absolute
+ * directory marker, such as <code>/</code> or <code>~</code>.
+ * The directories in the search path may be separated either
+ * by colons (Unix or Mac OS) or semicolons (Windows). If the file
+ * cannot be opened, the failure bit is set in the <code>stream</code>
+ * parameter, and the <code>openOnPath</code> function returns the
+ * empty string.
+ */
+
+std::string openOnPath(std::ifstream & stream, std::string path,
+ std::string filename);
+std::string openOnPath(std::ofstream & stream, std::string path,
+ std::string filename);
+
+/*
+ * Function: findOnPath
+ * Usage: string pathname = findOnPath(path, filename);
+ * ----------------------------------------------------
+ * Returns the canonical name of a file found using a search path.
+ * The <code>findOnPath</code> function is similar to
+ * <code>openOnPath</code>, except that it doesn't actually
+ * return an open stream. If no matching file is found,
+ * <code>findOnPath</code> returns the empty string.
+ */
+
+std::string findOnPath(std::string path, std::string filename);
+
+/*
+ * Function: deleteFile
+ * Usage: deleteFile(filename);
+ * ----------------------------
+ * Deletes the specified file. Errors are reported by calling
+ * <code>error</code>.
+ */
+
+void deleteFile(std::string filename);
+
+/*
+ * Function: renameFile
+ * Usage: renameFile(oldname, newname);
+ * ------------------------------------
+ * Renames a file. Errors are reported by calling
+ * <code>error</code> in the implementation.
+ */
+
+void renameFile(std::string oldname, std::string newname);
+
+/*
+ * Function: fileExists
+ * Usage: if (fileExists(filename)) ...
+ * ------------------------------------
+ * Returns <code>true</code> if the specified file exists.
+ */
+
+bool fileExists(std::string filename);
+
+/*
+ * Function: isFile
+ * Usage: if (isFile(filename)) ...
+ * --------------------------------
+ * Returns <code>true</code> if the specified file is a regular file.
+ */
+
+bool isFile(std::string filename);
+
+/*
+ * Function: isSymbolicLink
+ * Usage: if (isSymbolicLink(filename)) ...
+ * ----------------------------------------
+ * Returns <code>true</code> if the specified file is a symbolic link.
+ */
+
+bool isSymbolicLink(std::string filename);
+
+/*
+ * Function: isDirectory
+ * Usage: if (isDirectory(filename)) ...
+ * -------------------------------------
+ * Returns <code>true</code> if the specified file is a directory.
+ */
+
+bool isDirectory(std::string filename);
+
+/*
+ * Function: setCurrentDirectory
+ * Usage: setCurrentDirectory(filename);
+ * -------------------------------------
+ * Changes the current directory to the specified path.
+ */
+
+void setCurrentDirectory(std::string path);
+
+/*
+ * Function: getCurrentDirectory
+ * Usage: string filename = getCurrentDirectory();
+ * -----------------------------------------------
+ * Returns an absolute filename for the current directory.
+ */
+
+std::string getCurrentDirectory();
+
+/*
+ * Function: createDirectory
+ * Usage: createDirectory(path);
+ * -----------------------------
+ * Creates a new directory for the specified path. The
+ * <code>createDirectory</code> function does not report an error if
+ * the directory already exists. Unlike <code>createDirectoryPath</code>,
+ * <code>createDirectory</code> does not create missing directories
+ * along the path. If some component of <code>path</code> does
+ * not exist, this function signals an error.
+ */
+
+void createDirectory(std::string path);
+
+/*
+ * Function: createDirectoryPath
+ * Usage: createDirectoryPath(path);
+ * ---------------------------------
+ * Creates a new directory for the specified path. If intermediate
+ * components of <code>path</code> do not exist, this function creates
+ * them as needed.
+ */
+
+void createDirectoryPath(std::string path);
+
+/*
+ * Function: expandPathname
+ * Usage: string pathname = expandPathname(filename);
+ * --------------------------------------------------
+ * Expands a filename into a canonical name for the platform.
+ */
+
+std::string expandPathname(std::string filename);
+
+/*
+ * Function: listDirectory
+ * Usage: listDirectory(path, list);
+ * ---------------------------------
+ * Adds an alphabetized list of the files in the specified directory
+ * to the string vector <code>list</code>. This list excludes the
+ * names <code>.</code> and <code>..</code> entries.
+ */
+
+void listDirectory(std::string path, Vector<std::string> & list);
+void listDirectory(std::string path, std::vector<std::string> & list);
+
+/*
+ * Function: matchFilenamePattern
+ * Usage: if (matchFilenamePattern(filename, pattern)) ...
+ * -------------------------------------------------------
+ * Determines whether the filename matches the specified pattern. The
+ * pattern string is interpreted in much the same way that a Unix shell
+ * expands filenames and supports the following wildcard options:
+ *
+ *<pre>
+ * ? Matches any single character
+ * * Matches any sequence of characters
+ * [...] Matches any of the specified characters
+ * [^...] Matches any character <i>except</i> the specified ones
+ *</pre>
+ *
+ * The last two options allow a range of characters to be specified in the
+ * form <code>a-z</code>.
+ */
+
+bool matchFilenamePattern(std::string filename, std::string pattern);
+
+/*
+ * Function: getDirectoryPathSeparator
+ * Usage: string sep = getDirectoryPathSeparator();
+ * ------------------------------------------------
+ * Returns the standard directory path separator used on this platform.
+ */
+
+std::string getDirectoryPathSeparator();
+
+/*
+ * Function: getSearchPathSeparator
+ * Usage: string sep = getSearchPathSeparator();
+ * ---------------------------------------------
+ * Returns the standard search path separator used on this platform.
+ */
+
+std::string getSearchPathSeparator();
+
+#include "private/main.h"
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/foreach.h b/labb8/lib/StanfordCPPLib/foreach.h
new file mode 100755
index 0000000..15a758b
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/foreach.h
@@ -0,0 +1,217 @@
+/*
+ * File: foreach.h
+ * ---------------
+ * This file defines the <code>foreach</code> keyword, which implements
+ * a substitute for the range-based <code>for</code> loop from C++11.
+ * All iterable classes in the Stanford libraries import this file, so
+ * clients don't ordinarily need to do so explicitly. This version of
+ * <code>foreach</code> also supports C++ strings and arrays.
+ */
+
+#ifndef _foreach_h
+#define _foreach_h
+
+/*
+ * Statement: foreach
+ * Usage: foreach (type var in collection) { ... }
+ * -----------------------------------------------
+ * The <code>foreach</code> statement steps through the elements in
+ * a collection. It works correctly with the collection classes in
+ * both the Standard Template Library and the Stanford C++ libraries,
+ * but can also be used with C++ strings and statically initialized
+ * arrays.
+ *
+ * <p>The following code, for example, prints every element in the
+ * string vector <code>lines</code>:
+ *
+ *<pre>
+ * foreach (string str in lines) {
+ * cout &lt;&lt; str &lt;&lt; endl;
+ * }
+ *</pre>
+ *
+ * Similarly, the following function calculates the sum of the character
+ * codes in a string:
+ *
+ *<pre>
+ * int sumCharacterCodes(string str) {
+ * int sum = 0;
+ * foreach (char ch in str) sum += ch;
+ * return sum;
+ * }
+ *</pre>
+ *
+ * As a simplification when iterating over maps, the <code>foreach</code>
+ * macro iterates through the keys rather than the key/value pairs.
+ */
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+#include <iterator>
+#include <map>
+#include <cstddef>
+#include <cstring>
+
+/* These #includes are for files that contain "in" as a token */
+
+#include <ios>
+#include <fstream>
+#include <sstream>
+using namespace std;
+
+/* Redefine the ios constants (one of which is "in") */
+
+static const ios::openmode IOS_APP = ios::app;
+static const ios::openmode IOS_ATE = ios::ate;
+static const ios::openmode IOS_BINARY = ios::binary;
+static const ios::openmode IOS_IN = ios::in;
+static const ios::openmode IOS_OUT = ios::out;
+static const ios::openmode IOS_TRUNC = ios::trunc;
+
+/* Private implementation namespace */
+
+namespace _fe {
+ struct Range {
+ virtual ~Range() { };
+ };
+
+ template <typename T>
+ struct ArrayRange : Range {
+ ArrayRange(const T *begin, const T *end) : iter(begin), end(end) { }
+ const T *iter;
+ const T *end;
+ };
+
+ template <typename CType>
+ struct CRange : Range {
+ CRange(const CType& c) :
+ cont(c), iter(cont.begin()), end(cont.end()) { }
+ CType cont;
+ typename CType::iterator iter, end;
+ };
+
+ template <typename KT, typename VT, typename CT, typename AT>
+ struct MapRange : Range {
+ MapRange(const map<KT,VT,CT,AT> & c) :
+ cont(c), iter(cont.begin()), end(cont.end()) { }
+ map<KT,VT,CT,AT> cont;
+ typename map<KT,VT,CT,AT>::iterator iter, end;
+ };
+
+/*
+ * The State struct glues together all of these pieces and
+ * stores all of the information throughout the loops.
+ */
+
+ struct State {
+ State() : state(0), itr(NULL) { }
+ ~State() { delete itr; }
+ int state;
+ Range *itr;
+ };
+
+/* General hook function */
+
+ template <typename DowncastType, typename ValueType>
+ ValueType HookImpl(State& fe) {
+ DowncastType *ip = (DowncastType *) fe.itr;
+ if (ip->iter == ip->end) {
+ fe.state = 2;
+ return ValueType();
+ }
+ fe.state = 1;
+ ValueType vp = *ip->iter; /* Subtle implementation note: */
+ ++ip->iter; /* Using *ip->iter++ here would */
+ return vp; /* require copying the iterator. */
+ }
+
+/* Foreach implementation for containers */
+
+ template <typename CType>
+ CRange<CType> *Init(State & fe, const CType & collection) {
+ fe.itr = new CRange<CType>(collection);
+ return (CRange<CType>*) fe.itr;
+ }
+
+ template <typename CType>
+ typename iterator_traits<typename CType::iterator>::value_type
+ Hook(State & fe, CRange<CType> *) {
+ return HookImpl<CRange<CType>,
+ typename iterator_traits<typename CType::iterator>::value_type>(fe);
+ }
+
+/* For maps */
+
+ template <typename K, typename V, typename C, typename A>
+ MapRange<K,V,C,A> *Init(State & fe, const map<K,V,C,A> & collection) {
+ fe.itr = new MapRange<K,V,C,A>(collection);
+ return (MapRange<K,V,C,A>*) fe.itr;
+ }
+
+ template <typename DowncastType, typename ValueType>
+ ValueType MapHookImpl(State & fe) {
+ DowncastType *ip = (DowncastType *) fe.itr;
+ if (ip->iter == ip->end) {
+ fe.state = 2;
+ return ValueType();
+ }
+ fe.state = 1;
+ ValueType key = ip->iter->first;
+ ++ip->iter;
+ return key;
+ }
+
+ template <typename K, typename V, typename C, typename A>
+ K Hook(State & fe, MapRange<K,V,C,A> *) {
+ return MapHookImpl<MapRange<K,V,C,A>,K>(fe);
+ }
+
+/* For C strings */
+
+ template <size_t n>
+ ArrayRange<char> *Init(State & fe, char (&str)[n]) {
+ fe.itr = new ArrayRange<char>(str, str + strlen(str));
+ return (ArrayRange<char>*) fe.itr;
+ }
+
+ template <size_t n>
+ ArrayRange<char> *Init(State & fe, const char (&str)[n]) {
+ fe.itr = new ArrayRange<char>(str, str + strlen(str));
+ return (ArrayRange<char>*) fe.itr;
+ }
+
+/* For arrays */
+
+ template <typename T, size_t n>
+ ArrayRange<T> *Init(State & fe, T (&arr)[n]) {
+ fe.itr = new ArrayRange<T>(arr, arr + n);
+ return (ArrayRange<T>*) fe.itr;
+ }
+
+ template <typename T, size_t n>
+ ArrayRange<T> *Init(State & fe, const T (&arr)[n]) {
+ fe.itr = new ArrayRange<T>(arr, arr + n);
+ return (ArrayRange<T>*) fe.itr;
+ }
+
+ template <typename T>
+ T Hook(State& fe, ArrayRange<T>*) {
+ return HookImpl<ArrayRange<T>, T>(fe);
+ }
+
+}
+
+/* The actual foreach and in macros */
+
+#define foreach(arg) \
+ for (_fe::State _fe; _fe.state < 2; ) \
+ for (arg)); _fe.state++ == 1; _fe.state = 0)
+
+#define in = _fe::Hook(_fe, _fe.state != 0 ? NULL : _fe::Init(_fe,
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/gevents.cpp b/labb8/lib/StanfordCPPLib/gevents.cpp
new file mode 100755
index 0000000..72043d6
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gevents.cpp
@@ -0,0 +1,335 @@
+/*
+ * File: gevents.cpp
+ * -----------------
+ * This file implements the machine-independent functions for the classes
+ * in the gevents.h interface. The actual functions for receiving events
+ * from the environment are implemented in the platform package.
+ */
+
+/*
+ * Implementation notes:
+ * ---------------------
+ * The classes in this hierarchy are defined in an unusual way
+ * for C++ in that all instance variables are part of the top-level
+ * class. The advantage of this design is that the GEvent class
+ * then has all of the memory it needs to store an event of any of
+ * its subclasses.
+ */
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <cctype>
+#include "error.h"
+#include "gevents.h"
+#include "gtimer.h"
+#include "gtypes.h"
+#include "map.h"
+#include "platform.h"
+using namespace std;
+
+/* Global variables */
+
+static Platform *pp = getPlatform();
+
+/* Implementation of GEvent class */
+
+GEvent::GEvent() {
+ eventClass = NULL_EVENT;
+ eventType = 0;
+ valid = false;
+ modifiers = 0;
+}
+
+EventClassType GEvent::getEventClass() const {
+ return eventClass;
+}
+
+EventType GEvent::getEventType() const {
+ return EventType(eventType);
+}
+
+double GEvent::getEventTime() const {
+ return eventTime;
+}
+
+int GEvent::getModifiers() const {
+ return modifiers;
+}
+
+string GEvent::toString() const {
+ if (eventClass == 0) {
+ return "GEvent(NULL)";
+ } else if (eventClass == WINDOW_EVENT) {
+ GWindowEvent windowEvent(*this);
+ return (&windowEvent)->toString();
+ } else if (eventClass == ACTION_EVENT) {
+ GActionEvent actionEvent(*this);
+ return (&actionEvent)->toString();
+ } else if (eventClass == MOUSE_EVENT) {
+ GMouseEvent mouseEvent(*this);
+ return (&mouseEvent)->toString();
+ } else if (eventClass == KEY_EVENT) {
+ GKeyEvent keyEvent(*this);
+ return (&keyEvent)->toString();
+ } else if (eventClass == TIMER_EVENT) {
+ GTimerEvent timerEvent(*this);
+ return (&timerEvent)->toString();
+ } else {
+ return "GEvent(?)";
+ }
+}
+
+bool GEvent::isValid() {
+ return valid;
+}
+
+void GEvent::setEventTime(double time) {
+ eventTime = time;
+}
+
+void GEvent::setModifiers(int modifiers) {
+ this->modifiers = modifiers;
+}
+
+GWindowEvent::GWindowEvent() {
+ valid = false;
+}
+
+GWindowEvent::GWindowEvent(GEvent e) {
+ valid = e.valid && e.eventClass == WINDOW_EVENT;
+ if (valid) {
+ eventClass = e.eventClass;
+ eventType = e.eventType;
+ modifiers = e.modifiers;
+ eventTime = e.eventTime;
+ gwd = e.gwd;
+ }
+}
+
+GWindowEvent::GWindowEvent(EventType type, const GWindow & gw) {
+ this->eventClass = WINDOW_EVENT;
+ this->eventType = int(type);
+ this->gwd = gw.gwd;
+ valid = true;
+}
+
+GWindow GWindowEvent::getGWindow() const {
+ return GWindow(gwd);
+}
+
+string GWindowEvent::toString() const {
+ if (!valid) return "GWindowEvent(?)";
+ ostringstream os;
+ os << "GWindowEvent:";
+ switch (eventType) {
+ case WINDOW_CLOSED: os << "WINDOW_CLOSED"; break;
+ case WINDOW_RESIZED: os << "WINDOW_RESIZED"; break;
+ }
+ os << "()";
+ return os.str();
+}
+
+GActionEvent::GActionEvent() {
+ valid = false;
+}
+
+GActionEvent::GActionEvent(GEvent e) {
+ valid = e.valid && e.eventClass == ACTION_EVENT;
+ if (valid) {
+ eventClass = e.eventClass;
+ eventType = e.eventType;
+ modifiers = e.modifiers;
+ eventTime = e.eventTime;
+ source = e.source;
+ actionCommand = e.actionCommand;
+ }
+}
+
+GActionEvent::GActionEvent(EventType type, GObject *source,
+ string actionCommand) {
+ this->eventClass = ACTION_EVENT;
+ this->eventType = int(type);
+ this->source = source;
+ this->actionCommand = actionCommand;
+ valid = true;
+}
+
+GObject *GActionEvent::getSource() const {
+ return source;
+}
+
+string GActionEvent::getActionCommand() const {
+ if (!valid) error("getActionCommand: Event is not valid");
+ return actionCommand;
+}
+
+string GActionEvent::toString() const {
+ if (!valid) return "GActionEvent(?)";
+ ostringstream os;
+ os << "GActionEvent:ACTION_PERFORMED(" << actionCommand << ")";
+ return os.str();
+}
+
+GMouseEvent::GMouseEvent() {
+ valid = false;
+}
+
+GMouseEvent::GMouseEvent(GEvent e) {
+ valid = e.valid && e.eventClass == MOUSE_EVENT;
+ if (valid) {
+ eventClass = e.eventClass;
+ eventType = e.eventType;
+ modifiers = e.modifiers;
+ eventTime = e.eventTime;
+ x = e.x;
+ y = e.y;
+ }
+}
+
+GMouseEvent::GMouseEvent(EventType type, const GWindow & gw,
+ double x, double y) {
+ this->eventClass = MOUSE_EVENT;
+ this->eventType = int(type);
+ this->gwd = gw.gwd;
+ this->x = x;
+ this->y = y;
+ valid = true;
+}
+
+GWindow GMouseEvent::getGWindow() const {
+ return GWindow(gwd);
+}
+
+double GMouseEvent::getX() const {
+ if (!valid) error("getX: Event is not valid");
+ return x;
+}
+
+double GMouseEvent::getY() const {
+ if (!valid) error("getY: Event is not valid");
+ return y;
+}
+
+string GMouseEvent::toString() const {
+ if (!valid) return "GMouseEvent(?)";
+ ostringstream os;
+ os << "GMouseEvent:";
+ switch (eventType) {
+ case MOUSE_PRESSED: os << "MOUSE_PRESSED"; break;
+ case MOUSE_RELEASED: os << "MOUSE_RELEASED"; break;
+ case MOUSE_CLICKED: os << "MOUSE_CLICKED"; break;
+ case MOUSE_MOVED: os << "MOUSE_MOVED"; break;
+ case MOUSE_DRAGGED: os << "MOUSE_DRAGGED"; break;
+ }
+ os << "(" << x << ", " << y << ")";
+ return os.str();
+}
+
+GKeyEvent::GKeyEvent() {
+ valid = false;
+}
+
+GKeyEvent::GKeyEvent(GEvent e) {
+ this->eventClass = KEY_EVENT;
+ valid = e.valid && e.eventClass == KEY_EVENT;
+ if (valid) {
+ eventClass = e.eventClass;
+ eventType = e.eventType;
+ modifiers = e.modifiers;
+ eventTime = e.eventTime;
+ keyChar = e.keyChar;
+ keyCode = e.keyCode;
+ }
+}
+
+GKeyEvent::GKeyEvent(EventType type, const GWindow & gw,
+ int keyChar, int keyCode) {
+ this->eventClass = KEY_EVENT;
+ this->eventType = int(type);
+ this->gwd = gw.gwd;
+ this->keyChar = keyChar;
+ this->keyCode = keyCode;
+ valid = true;
+}
+
+GWindow GKeyEvent::getGWindow() const {
+ return GWindow(gwd);
+}
+
+char GKeyEvent::getKeyChar() const {
+ if (!valid) error("getKey: Event is not valid");
+ return char(keyChar);
+ // Think about wide characters at some point
+}
+
+int GKeyEvent::getKeyCode() const {
+ if (!valid) error("getKey: Event is not valid");
+ return keyCode;
+}
+
+string GKeyEvent::toString() const {
+ if (!valid) return "GKeyEvent(?)";
+ ostringstream os;
+ os << "GKeyEvent:";
+ int ch = '\0';
+ switch (eventType) {
+ case KEY_PRESSED: os << "KEY_PRESSED"; ch = keyCode; break;
+ case KEY_RELEASED: os << "KEY_RELEASED"; ch = keyCode; break;
+ case KEY_TYPED: os << "KEY_TYPED"; ch = keyChar; break;
+ }
+ if (isprint(ch)) {
+ os << "('" << char(ch) << "')";
+ } else {
+ os << oct << "('\\" << ch << "')";
+ }
+ return os.str();
+}
+
+/* Timer events */
+
+GTimerEvent::GTimerEvent() {
+ valid = false;
+}
+
+GTimerEvent::GTimerEvent(GEvent e) {
+ valid = e.valid && e.eventClass == TIMER_EVENT;
+ if (valid) {
+ eventClass = e.eventClass;
+ eventType = e.eventType;
+ modifiers = e.modifiers;
+ eventTime = e.eventTime;
+ gtd = e.gtd;
+ }
+}
+
+GTimerEvent::GTimerEvent(EventType type, const GTimer & timer) {
+ this->eventClass = TIMER_EVENT;
+ this->eventType = int(type);
+ this->gtd = timer.gtd;
+ valid = true;
+}
+
+GTimer GTimerEvent::getGTimer() const {
+ return GTimer(gtd);
+}
+
+string GTimerEvent::toString() const {
+ if (!valid) return "GTimerEvent(?)";
+ return "GTimerEvent:TIMER_TICKED()";
+}
+
+/* Global event handlers */
+
+void waitForClick() {
+ waitForEvent(CLICK_EVENT);
+}
+
+GEvent waitForEvent(int mask) {
+ return pp->waitForEvent(mask);
+}
+
+GEvent getNextEvent(int mask) {
+ return pp->getNextEvent(mask);
+}
+
diff --git a/labb8/lib/StanfordCPPLib/gevents.h b/labb8/lib/StanfordCPPLib/gevents.h
new file mode 100755
index 0000000..49717f9
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gevents.h
@@ -0,0 +1,734 @@
+/*
+ * File: gevents.h
+ * ---------------
+ * This file defines the event types used in the StanfordCPPLib
+ * graphics libraries. The structure of this package is adapted from
+ * the Java event model.
+ * <include src="pictures/ClassHierarchies/GEventHierarchy-h.html">
+ */
+
+#ifndef _gevents_h
+#define _gevents_h
+
+#include <string>
+#include "gtimer.h"
+#include "gwindow.h"
+
+/*
+ * Type: EventClassType
+ * --------------------
+ * This enumeration type defines the event classes. The element values
+ * are each a single bit and can be added or ORed together to generate
+ * an event mask. The <code>CLICK_EVENT</code> class responds only to
+ * the MOUSE_CLICKED event type. The <code>ANY_EVENT</code> class
+ * selects any event.
+ */
+
+enum EventClassType {
+ NULL_EVENT = 0x000,
+ ACTION_EVENT = 0x010,
+ KEY_EVENT = 0x020,
+ TIMER_EVENT = 0x040,
+ WINDOW_EVENT = 0x080,
+ MOUSE_EVENT = 0x100,
+ CLICK_EVENT = 0x200,
+ ANY_EVENT = 0x3F0
+};
+
+/*
+ * Type: EventType
+ * ---------------
+ * This enumeration type defines the event types for all events.
+ */
+
+typedef enum {
+ WINDOW_CLOSED = WINDOW_EVENT + 1,
+ WINDOW_RESIZED = WINDOW_EVENT + 2,
+ ACTION_PERFORMED = ACTION_EVENT + 1,
+ MOUSE_CLICKED = MOUSE_EVENT + 1,
+ MOUSE_PRESSED = MOUSE_EVENT + 2,
+ MOUSE_RELEASED = MOUSE_EVENT + 3,
+ MOUSE_MOVED = MOUSE_EVENT + 4,
+ MOUSE_DRAGGED = MOUSE_EVENT + 5,
+ KEY_PRESSED = KEY_EVENT + 1,
+ KEY_RELEASED = KEY_EVENT + 2,
+ KEY_TYPED = KEY_EVENT + 3,
+ TIMER_TICKED = TIMER_EVENT + 1,
+} EventType;
+
+/*
+ * Type: ModifierCodes
+ * -------------------
+ * This enumeration type defines a set of constants used to check whether
+ * modifiers are in effect.
+ */
+
+enum ModifierCodes {
+ SHIFT_DOWN = 1 << 0,
+ CTRL_DOWN = 1 << 1,
+ META_DOWN = 1 << 2,
+ ALT_DOWN = 1 << 3,
+ ALT_GRAPH_DOWN = 1 << 4,
+ BUTTON1_DOWN = 1 << 5,
+ BUTTON2_DOWN = 1 << 6,
+ BUTTON3_DOWN = 1 << 7
+};
+
+/*
+ * Type: KeyCodes
+ * --------------
+ * This type defines the names of the key codes returned in a key event.
+ */
+
+enum KeyCodes {
+ BACKSPACE_KEY = 8,
+ TAB_KEY = 9,
+ ENTER_KEY = 10,
+ CLEAR_KEY = 12,
+ ESCAPE_KEY = 27,
+ PAGE_UP_KEY = 33,
+ PAGE_DOWN_KEY = 34,
+ END_KEY = 35,
+ HOME_KEY = 36,
+ LEFT_ARROW_KEY = 37,
+ UP_ARROW_KEY = 38,
+ RIGHT_ARROW_KEY = 39,
+ DOWN_ARROW_KEY = 40,
+ F1_KEY = 112,
+ F2_KEY = 113,
+ F3_KEY = 114,
+ F4_KEY = 115,
+ F5_KEY = 116,
+ F6_KEY = 117,
+ F7_KEY = 118,
+ F8_KEY = 119,
+ F9_KEY = 120,
+ F10_KEY = 121,
+ F11_KEY = 122,
+ F12_KEY = 123,
+ DELETE_KEY = 127,
+ HELP_KEY = 156
+};
+
+/* Forward definitions */
+
+class GWindowEvent;
+class GActionEvent;
+class GMouseEvent;
+class GKeyEvent;
+class GTimerEvent;
+class GObject;
+
+/*
+ * Class: GEvent
+ * -------------
+ * This class is the root of the hierarchy for all events.
+ * <include src="pictures/ClassHierarchies/GEventHierarchy.html">
+ *
+ * <p>The standard paradigm for using <code>GEvent</code> is illustrated
+ * by the following program, which allows the user to draw lines on the
+ * graphics window:
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * GLine *line;
+ * cout << "This program lets the user draw lines by dragging." << endl;
+ * while (true) {
+ * GMouseEvent e = waitForEvent(MOUSE_EVENT);
+ * if (e.getEventType() == MOUSE_PRESSED) {
+ * line = new GLine(e.getX(), e.getY(), e.getX(), e.getY());
+ * gw.add(line);
+ * } else if (e.getEventType() == MOUSE_DRAGGED) {
+ * line->setEndPoint(e.getX(), e.getY());
+ * }
+ * }
+ * }
+ *</pre>
+ */
+
+class GEvent {
+
+public:
+
+/*
+ * Friend constructor: GEvent
+ * Usage: GEvent event;
+ * --------------------
+ * Ensures that an event is properly initialized to a <code>NULL</code> event.
+ */
+
+ GEvent();
+
+/*
+ * Method: getEventClass
+ * Usage: EventClassType eventClass = e.getEventClass();
+ * -----------------------------------------------------
+ * Returns the enumerated type constant indicating the class of the
+ * event.
+ */
+
+ EventClassType getEventClass() const;
+
+/*
+ * Method: getEventType
+ * Usage: EventType type = e.getEventType();
+ * -----------------------------------------
+ * Returns the enumerated type constant corresponding to the specific
+ * event type.
+ */
+
+ EventType getEventType() const;
+
+/*
+ * Method: getEventTime
+ * Usage: double time = e.getEventTime();
+ * --------------------------------------
+ * Returns the system time in milliseconds at which the event occurred.
+ * To ensure portability among systems that represent time in different
+ * ways, the StanfordCPPLib packages use type <code>double</code> to
+ * represent time, which is always encoded as the number of milliseconds
+ * that have elapsed since 00:00:00 UTC on January 1, 1970, which is
+ * the conventional zero point for computer-based time systems.
+ */
+
+ double getEventTime() const;
+
+/*
+ * Method: getModifiers
+ * Usage: int modifiers = e.getModifiers();
+ * ----------------------------------------
+ * Returns an integer whose bits indicate what modifiers are in effect.
+ * To check whether the shift key is down, for example, one could use
+ * the following code:
+ *
+ *<pre>
+ * if (e.getModifiers() & SHIFT_DOWN) ...
+ *</pre>
+ */
+
+ int getModifiers() const;
+
+/*
+ * Method: toString
+ * Usage: string str = e.toString();
+ * ---------------------------------
+ * Converts the event to a human-readable representation of the event.
+ */
+
+ virtual std::string toString() const;
+
+/*
+ * Method: isValid
+ * Usage: if (e.isValid()) ...
+ * ---------------------------
+ * Returns <code>true</code> if the event is valid.
+ */
+
+ bool isValid();
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+/*
+ * Method: setEventTime
+ * Usage: e.setEventTime(time);
+ * ----------------------------
+ * Sets the event time field for this event. The event system needs
+ * access to this method, but conventional clients don't.
+ */
+
+ void setEventTime(double time);
+
+/*
+ * Method: setModifiers
+ * Usage: e.setModifiers(modifiers);
+ * ---------------------------------
+ * Sets the modifiers field for this event. The event system needs
+ * access to this method, but conventional clients don't.
+ */
+
+ void setModifiers(int modifiers);
+
+private:
+
+/*
+ * Instance variables
+ * ------------------
+ * Implementation note: All the variables from the subclasses are included
+ * in the outer class to make it possible to convert between general events
+ * and the various subclasses. By keeping all event classes the same size,
+ * this design avoids any issues of slicing off parts of the data during
+ * such conversions.
+ */
+
+/* General events */
+
+ EventClassType eventClass;
+ int eventType;
+ int modifiers;
+ double eventTime;
+ bool valid;
+ std::string sourceKey;
+
+/* Window, mouse, and key events */
+
+ GWindowData *gwd;
+
+/* Action events */
+
+ GObject *source;
+ std::string actionCommand;
+
+/* Mouse events */
+
+ double x;
+ double y;
+
+/* Key events */
+
+ int keyChar;
+ int keyCode;
+
+/* Timer events */
+
+ GTimerData *gtd;
+
+/* Friend specifications */
+
+friend class GWindowEvent;
+friend class GActionEvent;
+friend class GMouseEvent;
+friend class GKeyEvent;
+friend class GTimerEvent;
+
+};
+
+/*
+ * Function: waitForClick
+ * Usage: waitForClick();
+ * ----------------------
+ * Waits for a mouse click in any window, discarding any other events.
+ */
+
+void waitForClick();
+
+/*
+ * Function: waitForEvent
+ * Usage: GEvent e = waitForEvent(mask);
+ * -------------------------------------
+ * Dismisses the process until an event occurs whose type is covered by
+ * the event mask. The mask parameter is a combination of the events of
+ * interest. For example, to wait for a mouse event or an action event,
+ * clients can use the following call:
+ *
+ *<pre>
+ * e = waitForEvent(MOUSE_EVENT + ACTION_EVENT);
+ *</pre>
+ *
+ * The <code>mask</code> parameter is optional. If it is missing,
+ * <code>waitForEvent</code> accepts any event.
+ *
+ * <p>As a more sophisticated example, the following code is the canonical
+ * event loop for an animated application that needs to respond to mouse,
+ * key, and timer events:
+ *
+ *<pre>
+ * GTimer timer(ANIMATION_DELAY_IN_MILLISECONDS);
+ * timer.start();
+ * while (true) {
+ * GEvent e = waitForEvent(TIMER_EVENT + MOUSE_EVENT + KEY_EVENT);
+ * switch (e.getEventClass()) {
+ * case TIMER_EVENT:
+ * takeAnimationStep();
+ * break;
+ * case MOUSE_EVENT:
+ * handleMouseEvent(GMouseEvent(e));
+ * break;
+ * case KEY_EVENT:
+ * handleKeyEvent(GKeyEvent(e));
+ * break;
+ * }
+ * }
+ *</pre>
+ */
+
+GEvent waitForEvent(int mask = ANY_EVENT);
+
+/*
+ * Function: getNextEvent
+ * Usage: GEvent e = getNextEvent(mask);
+ * -------------------------------------
+ * Checks to see if there are any events of the desired type waiting on the
+ * event queue. If so, this function returns the event in exactly the same
+ * fashion as <code>waitForEvent</code>; if not, <code>getNextEvent</code>
+ * returns an invalid event. The <code>mask</code> parameter is optional.
+ * If it is missing, <code>getNextEvent</code> accepts any event.
+ */
+
+GEvent getNextEvent(int mask = ANY_EVENT);
+
+/*
+ * Class: GWindowEvent
+ * -------------------
+ * This event subclass represents a window event.
+ * Each <code>GWindowEvent</code> keeps track of the event type
+ * (<code>WINDOW_CLOSED</code>, <code>WINDOW_RESIZED</code>) along
+ * with the identity of the window.
+ */
+
+class GWindowEvent : public GEvent {
+
+public:
+
+/*
+ * Constructor: GWindowEvent
+ * Usage: GWindowEvent windowEvent(type, gw);
+ * ------------------------------------------
+ * Creates a <code>GWindowEvent</code> using the specified parameters.
+ */
+
+ GWindowEvent(EventType type, const GWindow & gw);
+
+/*
+ * Method: getGWindow
+ * Usage: GWindow gw = e.getGWindow();
+ * -----------------------------------
+ * Returns the graphics window in which this event occurred.
+ */
+
+ GWindow getGWindow() const;
+
+/*
+ * Method: toString
+ * Usage: string str = e.toString();
+ * ---------------------------------
+ * Converts the event to a human-readable representation of the event.
+ */
+
+ std::string toString() const;
+
+/* Private section */
+
+ GWindowEvent();
+ GWindowEvent(GEvent e);
+
+};
+
+/*
+ * Class: GActionEvent
+ * -------------------
+ * This event subclass represents an action event.
+ * Action events are generated by the classes in the
+ * <a href="GInteractor-class.html"><code>GInteractor</code></a>
+ * hierarchy. As an example, the following program displays
+ * a button that, when pushed, generates the message
+ * &ldquo;Please do not press this button again&rdquo;
+ * (with thanks to Douglas Adams&rsquo;s <i>Hitchhiker&rsquo;s
+ * Guide to the Galaxy</i>):
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * GButton *button = new GButton("RED");
+ * gw.addToRegion(button, "SOUTH");
+ * while (true) {
+ * GEvent e = waitForEvent(ACTION_EVENT | CLICK_EVENT);
+ * if (e.getEventType() == MOUSE_CLICKED) break;
+ * cout << "Please do not press this button again." << endl;
+ * }
+ * return 0;
+ * }
+ *</pre>
+ */
+
+class GActionEvent : public GEvent {
+
+public:
+
+/*
+ * Constructor: GActionEvent
+ * Usage: GActionEvent actionEvent(type, source, actionCommand);
+ * -------------------------------------------------------------
+ * Creates a <code>GActionEvent</code> using the specified parameters.
+ */
+
+ GActionEvent(EventType type, GObject *source, std::string actionCommand);
+
+/*
+ * Method: getSource
+ * Usage: GObject *gobj = e.getSource();
+ * -------------------------------------
+ * Returns a pointer to the <code>GObject</code> that generated this event.
+ */
+
+ GObject *getSource() const;
+
+/*
+ * Method: getActionCommand
+ * Usage: string cmd = e.getActionCommand();
+ * -----------------------------------------
+ * Returns the action command associated with this event.
+ */
+
+ std::string getActionCommand() const;
+
+/*
+ * Method: toString
+ * Usage: string str = e.toString();
+ * ---------------------------------
+ * Converts the event to a human-readable representation of the event.
+ */
+
+ std::string toString() const;
+
+/* Private section */
+
+ GActionEvent();
+ GActionEvent(GEvent e);
+
+};
+
+/*
+ * Class: GMouseEvent
+ * ------------------
+ * This event subclass represents a mouse event. Each mouse event
+ * records the event type (<code>MOUSE_PRESSED</code>,
+ * <code>MOUSE_RELEASED</code>, <code>MOUSE_CLICKED</code>,
+ * <code>MOUSE_MOVED</code>, <code>MOUSE_DRAGGED</code>) along
+ * with the coordinates of the event. Clicking the mouse generates
+ * three events in the following order: <code>MOUSE_PRESSED</code>,
+ * <code>MOUSE_RELEASED</code>, <code>MOUSE_CLICKED</code>.
+ *
+ * <p>As an example, the following program uses mouse events to let
+ * the user draw rectangles on the graphics window. The only
+ * complexity in this code is the use of the library functions
+ * <code>min</code> and <code>abs</code> to ensure that the
+ * dimensions of the rectangle are positive.
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * cout << "This program lets the user draw rectangles." << endl;
+ * GRect *rect;
+ * double startX;
+ * double startY;
+ * while (true) {
+ * GMouseEvent e = waitForEvent();
+ * if (e.getEventType() == MOUSE_PRESSED) {
+ * startX = e.getX();
+ * startY = e.getY();
+ * rect = new GRect(startX, startY, 0, 0);
+ * rect->setFilled(true);
+ * gw.add(rect);
+ * } else if (e.getEventType() == MOUSE_DRAGGED) {
+ * double x = min(e.getX(), startX);
+ * double y = min(e.getY(), startY);
+ * double width = abs(e.getX() - startX);
+ * double height = abs(e.getY() - startY);
+ * rect->setBounds(x, y, width, height);
+ * }
+ * }
+ * }
+ *</pre>
+ */
+
+class GMouseEvent : public GEvent {
+
+public:
+
+/*
+ * Constructor: GMouseEvent
+ * Usage: GMouseEvent mouseEvent(type, gw, x, y);
+ * ----------------------------------------------
+ * Creates a <code>GMouseEvent</code> using the specified parameters.
+ */
+
+ GMouseEvent(EventType type, const GWindow & gw, double x, double y);
+
+/*
+ * Method: getGWindow
+ * Usage: GWindow gw = e.getGWindow();
+ * -----------------------------------
+ * Returns the graphics window in which this event occurred.
+ */
+
+ GWindow getGWindow() const;
+
+/*
+ * Method: getX
+ * Usage: double x = getX();
+ * -------------------------
+ * Returns the <i>x</i> coordinate at which the event occurred relative
+ * to the window origin at the upper left corner of the window.
+ */
+
+ double getX() const;
+
+/*
+ * Method: getY
+ * Usage: double y = getY();
+ * -------------------------
+ * Returns the <i>y</i> coordinate at which the event occurred relative
+ * to the window origin at the upper left corner of the window.
+ */
+
+ double getY() const;
+
+/*
+ * Method: toString
+ * Usage: string str = e.toString();
+ * ---------------------------------
+ * Converts the event to a human-readable representation of the event.
+ */
+
+ std::string toString() const;
+
+/* Private section */
+
+ GMouseEvent();
+ GMouseEvent(GEvent e);
+
+};
+
+/*
+ * Class: GKeyEvent
+ * ----------------
+ * This event subclass represents a key event. Each key event records
+ * the event type along with two representations of the key. The
+ * <code>getKeyChar</code> function is more generally useful and
+ * returns the character after taking into account modifier keys.
+ * The <code>getKeyCode</code> function returns an integer identifying
+ * the key, which can be a function key as well as a standard key.
+ * The codes return by <code>getKeyCode</code> are listed in the
+ * <code>KeyCodes</code> enumeration.
+ */
+
+class GKeyEvent : public GEvent {
+
+public:
+
+/*
+ * Constructor: GKeyEvent
+ * Usage: GKeyEvent keyEvent(type, gw, keyChar, keyCode);
+ * ------------------------------------------------------
+ * Creates a <code>GKeyEvent</code> using the specified parameters.
+ */
+
+ GKeyEvent(EventType type, const GWindow & gw, int keyChar, int keyCode);
+
+/*
+ * Method: getGWindow
+ * Usage: GWindow gw = e.getGWindow();
+ * -----------------------------------
+ * Returns the graphics window in which this event occurred.
+ */
+
+ GWindow getGWindow() const;
+
+/*
+ * Method: getKeyChar
+ * Usage: char ch = e.getKeyChar();
+ * --------------------------------
+ * Returns the character represented by the keystroke, taking the modifier
+ * keys into account. For example, if the user types the <code>'a'</code>
+ * key with the shift key down, <code>getKeyChar</code> will return
+ * <code>'A'</code>. If the key code in the event does not correspond
+ * to a character, <code>getKeyChar</code> returns the null character.
+ */
+
+ char getKeyChar() const;
+
+/*
+ * Method: getKeyCode
+ * Usage: int key = getKeyCode();
+ * ------------------------------
+ * Returns the integer code associated with the key in the event.
+ */
+
+ int getKeyCode() const;
+
+/*
+ * Method: toString
+ * Usage: string str = e.toString();
+ * ---------------------------------
+ * Converts the event to a human-readable representation of the event.
+ */
+
+ std::string toString() const;
+
+/* Private section */
+
+ GKeyEvent();
+ GKeyEvent(GEvent e);
+
+};
+
+/*
+ * Class: GTimerEvent
+ * ------------------
+ * This event subclass represents a timer event. Timer events are
+ * generated by a <a href="GTimer-class.html"><code>GTimer</code></a>
+ * object, which produces a new event at a fixed interval measured in
+ * milliseconds. As an example, the following program generates a
+ * timer event every two seconds, stopping when the user clicks
+ * somewhere in the window:
+ *
+ *<pre>
+ * int main() {
+ * cout << "This program generates timer events." << endl;
+ * GTimer timer(2000);
+ * timer.start();
+ * while (true) {
+ * GEvent e = waitForEvent(CLICK_EVENT | TIMER_EVENT);
+ * if (e.getEventType() == MOUSE_CLICKED) break;
+ * cout << "Timer ticked" << endl;
+ * }
+ * return 0;
+ * }
+ *</pre>
+ */
+
+class GTimerEvent : public GEvent {
+
+public:
+
+/*
+ * Constructor: GTimerEvent
+ * Usage: GTimerEvent timerEvent(type, timer);
+ * -------------------------------------------
+ * Creates a <code>GTimerEvent</code> for the specified timer.
+ */
+
+ GTimerEvent(EventType type, const GTimer & timer);
+
+/*
+ * Method: getGTimer
+ * Usage: GTimer timer = e.getGTimer();
+ * ------------------------------------
+ * Returns the timer that generated this event.
+ */
+
+ GTimer getGTimer() const;
+
+/*
+ * Method: toString
+ * Usage: string str = e.toString();
+ * ---------------------------------
+ * Converts the event to a human-readable representation of the event.
+ */
+
+ std::string toString() const;
+
+/* Private section */
+
+ GTimerEvent();
+ GTimerEvent(GEvent e);
+
+};
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/ginteractors.cpp b/labb8/lib/StanfordCPPLib/ginteractors.cpp
new file mode 100755
index 0000000..8075372
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/ginteractors.cpp
@@ -0,0 +1,204 @@
+/*
+ * File: gobjects.cpp
+ * ------------------
+ * This file implements the ginteractors.h interface.
+ */
+
+#include <iostream>
+#include <sstream>
+#include "gevents.h"
+#include "ginteractors.h"
+#include "gobjects.h"
+#include "gtypes.h"
+#include "gwindow.h"
+#include "platform.h"
+
+static Platform *pp = getPlatform();
+
+/*
+ * Implementation notes: GInteractor class
+ * ---------------------------------------
+ */
+
+GInteractor::GInteractor() {
+ actionCommand = "";
+}
+
+void GInteractor::setActionCommand(string cmd) {
+ actionCommand = cmd;
+ pp->setActionCommand(this, cmd);
+}
+
+string GInteractor::getActionCommand() {
+ return actionCommand;
+}
+
+void GInteractor::setSize(const GDimension & size) {
+ setSize(size.getWidth(), size.getHeight());
+}
+
+void GInteractor::setSize(double width, double height) {
+ pp->setSize(this, width, height);
+}
+
+void GInteractor::setBounds(const GRectangle & rect) {
+ setLocation(rect.getX(), rect.getY());
+ setSize(rect.getWidth(), rect.getHeight());
+}
+
+void GInteractor::setBounds(double x, double y, double width, double height) {
+ setLocation(x, y);
+ setSize(width, height);
+}
+
+GRectangle GInteractor::getBounds() const {
+ GDimension size = pp->getSize((GObject *) this);
+ return GRectangle(x, y, size.getWidth(), size.getHeight());
+}
+
+/*
+ * Implementation notes: GButton class
+ * -----------------------------------
+ */
+
+GButton::GButton(string label) {
+ this->label = label;
+ pp->createGButton(this, label);
+}
+
+string GButton::getType() const {
+ return "GButton";
+}
+
+string GButton::toString() const {
+ ostringstream oss;
+ oss << "GButton(\"" << label << "\")";
+ return oss.str();
+}
+
+/*
+ * Implementation notes: GCheckBox class
+ * -------------------------------------
+ */
+
+GCheckBox::GCheckBox(string label) {
+ this->label = label;
+ pp->createGCheckBox(this, label);
+}
+
+bool GCheckBox::isSelected() {
+ return pp->isSelected(this);
+}
+
+void GCheckBox::setSelected(bool state) {
+ pp->setSelected(this, state);
+}
+
+string GCheckBox::getType() const {
+ return "GCheckBox";
+}
+
+string GCheckBox::toString() const {
+ ostringstream oss;
+ oss << "GCheckBox(\"" << label << "\")";
+ return oss.str();
+}
+
+/*
+ * Implementation notes: GSlider class
+ * -----------------------------------
+ */
+
+GSlider::GSlider() {
+ create(0, 100, 50);
+}
+
+GSlider::GSlider(int min, int max, int value) {
+ create(min, max, value);
+}
+
+int GSlider::getValue() {
+ return pp->getValue(this);
+}
+
+void GSlider::setValue(int value) {
+ pp->setValue(this, value);
+}
+
+string GSlider::getType() const {
+ return "GSlider";
+}
+
+string GSlider::toString() const {
+ ostringstream oss;
+ oss << "GSlider()";
+ return oss.str();
+}
+
+void GSlider::create(int min, int max, int value) {
+ this->min = min;
+ this->max = max;
+ pp->createGSlider(this, min, max, value);
+}
+
+/*
+ * Implementation notes: GTextField class
+ * --------------------------------------
+ */
+
+GTextField::GTextField() {
+ pp->createGTextField(this, 10);
+}
+
+GTextField::GTextField(int nChars) {
+ pp->createGTextField(this, nChars);
+}
+
+string GTextField::getText() {
+ return pp->getText(this);
+}
+
+void GTextField::setText(string str) {
+ pp->setText(this, str);
+}
+
+string GTextField::getType() const {
+ return "GTextField";
+}
+
+string GTextField::toString() const {
+ ostringstream oss;
+ oss << "GTextField()";
+ return oss.str();
+}
+
+/*
+ * Implementation notes: GChooser class
+ * ------------------------------------
+ */
+
+GChooser::GChooser() {
+ pp->createGChooser(this);
+}
+
+void GChooser::addItem(string item) {
+ pp->addItem(this, item);
+}
+
+string GChooser::getSelectedItem() {
+ return pp->getSelectedItem(this);
+}
+
+void GChooser::setSelectedItem(string item) {
+ pp->setSelectedItem(this, item);
+}
+
+string GChooser::getType() const {
+ return "GChooser";
+}
+
+string GChooser::toString() const {
+ ostringstream oss;
+ oss << "GChooser()";
+ return oss.str();
+}
diff --git a/labb8/lib/StanfordCPPLib/ginteractors.h b/labb8/lib/StanfordCPPLib/ginteractors.h
new file mode 100755
index 0000000..f439324
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/ginteractors.h
@@ -0,0 +1,370 @@
+/*
+ * File: ginteractors.h
+ * --------------------
+ * This file exports a hierarchy of graphical interactors similar to those
+ * provided in the Java Swing libraries.
+ * <include src="pictures/ClassHierarchies/GInteractorHierarchy-h.html">
+ */
+
+#ifndef _ginteractors_h
+#define _ginteractors_h
+
+#include "gobjects.h"
+#include "gtypes.h"
+#include "gwindow.h"
+#include "vector.h"
+
+/*
+ * Class: GInteractor
+ * ------------------
+ * This abstract class is the superclass for all graphical interactors.
+ * In most applications, interactors will be added to a control strip
+ * along one of the sides of the <code>GWindow</code>, but they can
+ * also be placed in specific positions just like any other
+ * <code>GObject</code>.
+ * <include src="pictures/ClassHierarchies/GInteractorHierarchy.html">
+ */
+
+class GInteractor : public GObject {
+
+public:
+
+/*
+ * Method: setActionCommand
+ * Usage: interactor.setActionCommand(cmd);
+ * ----------------------------------------
+ * Sets the action command to the indicated string. If the string is not
+ * empty, activating the interactor generates a <code>GActionEvent</code>.
+ */
+
+ void setActionCommand(std::string cmd);
+
+/*
+ * Method: getActionCommand
+ * Usage: string cmd = interactor.getActionCommand();
+ * --------------------------------------------------
+ * Returns the action command associated with the interactor.
+ */
+
+ std::string getActionCommand();
+
+/*
+ * Method: setSize
+ * Usage: interactor.setSize(size);
+ * interactor.setSize(width, height);
+ * -----------------------------------------
+ * Changes the size of the interactor to the specified width and height.
+ */
+
+ void setSize(const GDimension & size);
+ void setSize(double width, double height);
+
+/*
+ * Method: setBounds
+ * Usage: interactor.setBounds(rect);
+ * interactor.setBounds(x, y, width, height);
+ * -------------------------------------------------
+ * Changes the bounds of the interactor to the specified values.
+ */
+
+ void setBounds(const GRectangle & size);
+ void setBounds(double x, double y, double width, double height);
+
+/* Prototypes for the virtual methods */
+
+ virtual GRectangle getBounds() const;
+
+protected:
+
+ GInteractor();
+
+ std::string actionCommand;
+
+};
+
+/*
+ * Class: GButton
+ * --------------
+ * This interactor subclass represents an onscreen button. The following
+ * program displays a button that, when pressed, generates the message
+ * &ldquo;Please do not press this button again&rdquo;
+ * (with thanks to Douglas Adams&rsquo;s <i>Hitchhiker&rsquo;s
+ * Guide to the Galaxy</i>):
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * GButton *button = new GButton("RED");
+ * gw.addToRegion(button, "SOUTH");
+ * while (true) {
+ * GEvent e = waitForEvent(ACTION_EVENT | CLICK_EVENT);
+ * if (e.getEventType() == MOUSE_CLICKED) break;
+ * cout << "Please do not press this button again." << endl;
+ * }
+ * return 0;
+ * }
+ *</pre>
+ */
+
+class GButton : public GInteractor {
+
+public:
+
+/*
+ * Constructor: GButton
+ * Usage: GButton *button = new GButton(label);
+ * --------------------------------------------
+ * Creates a <code>GButton</code> with the specified label. This
+ * constructor also sets the action command for the button to the
+ * label string.
+ */
+
+ GButton(std::string label);
+
+/* Prototypes for the virtual methods */
+
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+private:
+ std::string label;
+
+};
+
+/*
+ * Class: GCheckBox
+ * ----------------
+ * This interactor subclass represents an onscreen check box. Clicking
+ * once on the check box selects it; clicking again removes the selection.
+ * If a <code>GCheckBox</code> has an action command, clicking on the box
+ * generates a <code>GActionEvent</code>.
+ * <include src="pictures/GInteractorDiagrams/GCheckBox.html">
+ */
+
+class GCheckBox : public GInteractor {
+
+public:
+
+/*
+ * Constructor: GCheckBox
+ * Usage: GCheckBox *chkbox = new GCheckBox(label);
+ * ------------------------------------------------
+ * Creates a <code>GCheckBox</code> with the specified label. In contrast
+ * to the <code>GButton</code> constructor, this constructor does not set
+ * an action command.
+ */
+
+ GCheckBox(std::string label);
+
+/*
+ * Method: setSelected
+ * Usage: chkbox->setSelected(state);
+ * ----------------------------------
+ * Sets the state of the check box.
+ */
+
+ void setSelected(bool state);
+
+/*
+ * Method: isSelected
+ * Usage: if (chkbox->isSelected()) ...
+ * ------------------------------------
+ * Returns <code>true</code> if the check box is selected.
+ */
+
+ bool isSelected();
+
+/* Prototypes for the virtual methods */
+
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+private:
+ std::string label;
+
+};
+
+/*
+ * Class: GSlider
+ * --------------
+ * This interactor subclass represents an onscreen slider. Dragging
+ * the slider control generates an <code>ActionEvent</code> if the
+ * slider has a nonempty action command.
+ * <include src="pictures/GInteractorDiagrams/GSlider.html">
+ */
+
+class GSlider : public GInteractor {
+
+public:
+
+/*
+ * Constructor: GSlider
+ * Usage: GSlider *slider = new GSlider();
+ * GSlider *slider = new GSlider(min, max, value);
+ * ------------------------------------------------------
+ * Creates a horizontal <code>GSlider</code>. The second form allows
+ * the client to specify the minimum value, maximum value, and current
+ * value of the slider. The first form is equivalent to calling
+ * <code>GSlider(0, 100, 50)</code>. Assigning an action command
+ * to the slider causes the slider to generate an action event whenever
+ * the slider value changes.
+ */
+
+ GSlider();
+ GSlider(int min, int max, int value);
+
+/*
+ * Method: setValue
+ * Usage: slider->setValue(value);
+ * -------------------------------
+ * Sets the current value of the slider.
+ */
+
+ void setValue(int value);
+
+/*
+ * Method: getValue
+ * Usage: int value = slider->getValue();
+ * --------------------------------------
+ * Returns the current value of the slider.
+ */
+
+ int getValue();
+
+/* Prototypes for the virtual methods */
+
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+private:
+ void create(int min, int max, int value);
+ int min;
+ int max;
+
+};
+
+/*
+ * Class: GTextField
+ * -----------------
+ * This interactor subclass represents a text field for entering short
+ * text strings. Hitting enter in a text field generates a
+ * <code>GActionEvent</code> if the text field has a nonempty action command.
+
+ */
+
+class GTextField : public GInteractor {
+
+public:
+
+/*
+ * Constructor: GTextField
+ * Usage: GTextField *field = new GTextField();
+ * GTextField *field = new GTextField(nChars);
+ * --------------------------------------------------
+ * Creates a text field capable of holding <code>nChars</code> characters,
+ * which defaults to 10. Assigning an action command to the text field
+ * causes it to generate an action event whenever the user types the
+ * ENTER key.
+ */
+
+ GTextField();
+ GTextField(int nChars);
+
+/*
+ * Method: setText
+ * Usage: field->setText(str);
+ * ---------------------------
+ * Sets the text of the field to the specified string.
+ */
+
+ void setText(std::string str);
+
+/*
+ * Method: getText
+ * Usage: string str = field->getText();
+ * -------------------------------------
+ * Returns the contents of the text field.
+ */
+
+ std::string getText();
+
+/* Prototypes for the virtual methods */
+
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+};
+
+/*
+ * Class: GChooser
+ * ---------------
+ * This interactor subclass represents a selectable list. The
+ * <code>GChooser</code> constructor creates an empty chooser.
+ * Once the chooser has been created, clients can use <code>addItem</code>
+ * to add the options. For example, the following code creates a
+ * <code>GChooser</code> containing the four strings
+ * <code>"Small"</code>, <code>"Medium"</code>, <code>"Large"</code>,
+ * and <code>"X-Large"</code>:
+ *
+ *<pre>
+ * GChooser *sizeChooser = new GChooser();
+ * sizeChooser->addItem("Small");
+ * sizeChooser->addItem("Medium");
+ * sizeChooser->addItem("Large");
+ * sizeChooser->addItem("X-Large");
+ *</pre>
+ *<include src="pictures/GInteractorDiagrams/GChooser.html">
+ */
+
+class GChooser : public GInteractor {
+
+public:
+
+/*
+ * Constructor: GChooser
+ * Usage: GChooser *chooser = new GChooser();
+ * ------------------------------------------
+ * Creates a chooser that initially contains no items, which are added
+ * using the <code>addItem</code> method. Assigning an action command
+ * to the chooser causes it to generate an action event whenever the
+ * user selects an item.
+ */
+
+ GChooser();
+
+/*
+ * Method: addItem
+ * Usage: chooser->addItem(item);
+ * ------------------------------
+ * Adds a new item consisting of the specified string.
+ */
+
+ void addItem(std::string item);
+
+/*
+ * Method: setSelectedItem
+ * Usage: chooser->setSelectedItem(item);
+ * --------------------------------------
+ * Sets the chooser so that it shows the specified item. If the item
+ * does not exist in the chooser, no change occurs.
+ */
+
+ void setSelectedItem(std::string item);
+
+/*
+ * Method: getSelectedItem
+ * Usage: string item = chooser->getSelectedItem();
+ * ------------------------------------------------
+ * Returns the current item selected in the chooser.
+ */
+
+ std::string getSelectedItem();
+
+/* Prototypes for the virtual methods */
+
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+};
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/gmath.cpp b/labb8/lib/StanfordCPPLib/gmath.cpp
new file mode 100755
index 0000000..a5ff934
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gmath.cpp
@@ -0,0 +1,50 @@
+/*
+ * File: gmath.cpp
+ * ---------------
+ * This file implements the gmath.h interface. In all cases, the
+ * implementation for each function requires only one line of code,
+ * which makes detailed documentation unnecessary.
+ */
+
+#include <cmath>
+#include "gmath.h"
+#include "gtypes.h"
+
+extern const double PI = 3.14159265358979323846;
+extern const double E = 2.71828182845904523536;
+
+double sinDegrees(double angle) {
+ return sin(toRadians(angle));
+}
+
+double cosDegrees(double angle) {
+ return cos(toRadians(angle));
+}
+
+double tanDegrees(double angle) {
+ return tan(toRadians(angle));
+}
+
+double toDegrees(double radians) {
+ return radians * 180 / PI;
+}
+
+double toRadians(double degrees) {
+ return degrees * PI / 180;
+}
+
+double vectorDistance(const GPoint & pt) {
+ return vectorDistance(pt.getX(), pt.getY());
+}
+
+double vectorDistance(double x, double y) {
+ return sqrt(x * x + y * y);
+}
+
+double vectorAngle(const GPoint & pt) {
+ return vectorAngle(pt.getX(), pt.getY());
+}
+
+double vectorAngle(double x, double y) {
+ return (x == 0 && y == 0) ? 0 : toDegrees(atan2(-y, x));
+}
diff --git a/labb8/lib/StanfordCPPLib/gmath.h b/labb8/lib/StanfordCPPLib/gmath.h
new file mode 100755
index 0000000..7dc8aab
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gmath.h
@@ -0,0 +1,104 @@
+/*
+ * File: gmath.h
+ * -------------
+ * This file exports several functions for working with graphical
+ * geometry along with the mathematical constants <code>PI</code>
+ * and <code>E</code>.
+ */
+
+#ifndef _gmath_h
+#define _gmath_h
+
+#include "gtypes.h"
+
+/*
+ * Constant: PI
+ * ------------
+ * The mathematical constant pi, which is the ratio of the circumference
+ * of a circle to its diameter.
+ */
+
+extern const double PI;
+
+/*
+ * Constant: E
+ * -----------
+ * The mathematical constant e, which is the base of natural logarithms.
+ */
+
+extern const double E;
+
+/*
+ * Function: sinDegrees
+ * Usage: double sine = sinDegrees(angle);
+ * ---------------------------------------
+ * Returns the trigonometric sine of <code>angle</code>, which is
+ * expressed in degrees.
+ */
+
+double sinDegrees(double angle);
+
+/*
+ * Function: cosDegrees
+ * Usage: double cosine = cosDegrees(angle);
+ * -----------------------------------------
+ * Returns the trigonometric cosine of <code>angle</code>, which is
+ * expressed in degrees.
+ */
+
+double cosDegrees(double angle);
+
+/*
+ * Function: tanDegrees
+ * Usage: double tangent = tanDegrees(angle);
+ * ------------------------------------------
+ * Returns the trigonometric tangent of <code>angle</code>, which is
+ * expressed in degrees.
+ */
+
+double tanDegrees(double angle);
+
+/*
+ * Function: toDegrees
+ * Usage: double degrees = toDegrees(radians);
+ * -------------------------------------------
+ * Converts an angle from radians to degrees.
+ */
+
+double toDegrees(double radians);
+
+/*
+ * Function: toRadians
+ * Usage: double radians = toRadians(degrees);
+ * -------------------------------------------
+ * Converts an angle from degrees to radians.
+ */
+
+double toRadians(double degrees);
+
+/*
+ * Function: vectorDistance
+ * Usage: double r = vectorDistance(pt);
+ * double r = vectorDistance(x, y);
+ * ---------------------------------------
+ * Computes the distance between the origin and the specified point.
+ */
+
+double vectorDistance(const GPoint & pt);
+double vectorDistance(double x, double y);
+
+/*
+ * Function: vectorAngle
+ * Usage: double angle = vectorAngle(pt);
+ * double angle = vectorAngle(x, y);
+ * ----------------------------------------
+ * Returns the angle in degrees from the origin to the specified point.
+ * This function takes account of the fact that the graphics coordinate
+ * system is flipped in the <i>y</i> direction from the traditional
+ * Cartesian plane.
+ */
+
+double vectorAngle(const GPoint & pt);
+double vectorAngle(double x, double y);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/gobjects.cpp b/labb8/lib/StanfordCPPLib/gobjects.cpp
new file mode 100755
index 0000000..ea22894
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gobjects.cpp
@@ -0,0 +1,1033 @@
+/*
+ * File: gobjects.cpp
+ * ------------------
+ * This file implements the gobjects.h interface.
+ */
+
+#include <cmath>
+#include <iostream>
+#include <sstream>
+#include "gevents.h"
+#include "gmath.h"
+#include "gobjects.h"
+#include "gtypes.h"
+#include "gwindow.h"
+#include "platform.h"
+#include "vector.h"
+
+static Platform *pp = getPlatform();
+
+const double LINE_TOLERANCE = 1.5;
+const double ARC_TOLERANCE = 2.5;
+const double DEFAULT_CORNER = 10;
+const string DEFAULT_GLABEL_FONT = "Dialog-13";
+
+static double dsq(double x0, double y0, double x1, double y1);
+
+double GObject::getX() const {
+ return x;
+}
+
+double GObject::getY() const {
+ return y;
+}
+
+GPoint GObject::getLocation() const {
+ return GPoint(x, y);
+}
+
+void GObject::setLocation(const GPoint & pt) {
+ setLocation(pt.getX(), pt.getY());
+}
+
+void GObject::setLocation(double x, double y) {
+ this->x = x;
+ this->y = y;
+ pp->setLocation(this, x, y);
+}
+
+void GObject::move(double dx, double dy) {
+ setLocation(x + dx, y + dy);
+}
+
+double GObject::getWidth() const {
+ return getBounds().getWidth();
+}
+
+double GObject::getHeight() const {
+ return getBounds().getHeight();
+}
+
+GDimension GObject::getSize() const {
+ GRectangle bounds = getBounds();
+ return GDimension(bounds.getWidth(), bounds.getHeight());
+}
+
+void GObject::setLineWidth(double lineWidth) {
+ this->lineWidth = lineWidth;
+ pp->setLineWidth(this, lineWidth);
+}
+
+double GObject::getLineWidth() const {
+ return lineWidth;
+}
+
+void GObject::setColor(string color) {
+ setColor(convertColorToRGB(color));
+}
+
+void GObject::setColor(int rgb) {
+ this->color = convertRGBToColor(rgb);
+ pp->setColor(this, this->color);
+}
+
+string GObject::getColor() const {
+ return color;
+}
+
+void GObject::scale(double sf) {
+ scale(sf, sf);
+}
+
+void GObject::scale(double sx, double sy) {
+ // Apply local transform
+ transformed = true;
+ pp->scale(this, sx, sy);
+}
+
+void GObject::rotate(double theta) {
+ // Apply local transform
+ transformed = true;
+ pp->rotate(this, theta);
+}
+
+void GObject::setVisible(bool flag) {
+ visible = flag;
+ pp->setVisible(this, flag);
+}
+
+bool GObject::isVisible() const {
+ return visible;
+}
+
+void GObject::sendForward() {
+ GCompound *parent = getParent();
+ if (parent != NULL) parent->sendForward(this);
+}
+
+void GObject::sendToFront() {
+ GCompound *parent = getParent();
+ if (parent != NULL) parent->sendToFront(this);
+}
+
+void GObject::sendBackward() {
+ GCompound *parent = getParent();
+ if (parent != NULL) parent->sendBackward(this);
+}
+
+void GObject::sendToBack() {
+ GCompound *parent = getParent();
+ if (parent != NULL) parent->sendToBack(this);
+}
+
+bool GObject::contains(GPoint pt) const {
+ return contains(pt.getX(), pt.getY());
+}
+
+bool GObject::contains(double x, double y) const {
+ if (transformed) return pp->contains(this, x, y);
+ return getBounds().contains(x, y);
+}
+
+GCompound *GObject::getParent() const {
+ return parent;
+}
+
+GObject::GObject() {
+ x = 0;
+ y = 0;
+ color = "";
+ lineWidth = 1.0;
+ transformed = false;
+ visible = true;
+}
+
+GObject::~GObject() {
+ pp->deleteGObject(this);
+}
+
+/*
+ * Implementation notes: GRect class
+ * ---------------------------------
+ * The GRect class is the most straightforward of the shape classes.
+ */
+
+GRect::GRect(double width, double height) {
+ createGRect(width, height);
+}
+
+GRect::GRect(double x, double y, double width, double height) {
+ createGRect(width, height);
+ setLocation(x, y);
+}
+
+GRect::~GRect() {
+ /* Empty */
+}
+
+void GRect::setSize(const GDimension & size) {
+ setSize(size.getWidth(), size.getHeight());
+}
+
+void GRect::setSize(double width, double height) {
+ if (transformed) error("setSize: Object has been transformed");
+ this->width = width;
+ this->height = height;
+ pp->setSize(this, width, height);
+}
+
+void GRect::setBounds(const GRectangle & bounds) {
+ setLocation(bounds.getX(), bounds.getY());
+ setSize(bounds.getWidth(), bounds.getHeight());
+}
+
+void GRect::setBounds(double x, double y, double width, double height) {
+ setLocation(x, y);
+ setSize(width, height);
+}
+
+GRectangle GRect::getBounds() const {
+ if (transformed) return pp->getBounds(this);
+ return GRectangle(x, y, width, height);
+}
+
+void GRect::setFilled(bool flag) {
+ fillFlag = true;
+ pp->setFilled(this, flag);
+}
+
+bool GRect::isFilled() const {
+ return fillFlag;
+}
+
+void GRect::setFillColor(string color) {
+ fillColor = color;
+ if (fillColor != "") {
+ fillColor = convertRGBToColor(convertColorToRGB(color));
+ }
+ pp->setFillColor(this, fillColor);
+}
+
+void GRect::setFillColor(int rgb) {
+ fillColor = convertRGBToColor(rgb);
+ pp->setFillColor(this, fillColor);
+}
+
+string GRect::getFillColor() const {
+ return fillColor;
+}
+
+string GRect::getType() const {
+ return "GRect";
+}
+
+string GRect::toString() const {
+ ostringstream oss;
+ oss << "GRect(" << x << ", " << y << ", "
+ << width << ", " << height << ")";
+ return oss.str();
+}
+
+GRect::GRect() {
+ /* Called only by the GRoundRect and G3DRect subclasses */
+}
+
+void GRect::createGRect(double width, double height) {
+ this->x = 0;
+ this->y = 0;
+ this->width = width;
+ this->height = height;
+ fillFlag = false;
+ fillColor = "";
+ pp->createGRect(this, width, height);
+}
+
+/*
+ * Implementation notes: GRoundRect class
+ * --------------------------------------
+ * Most of the GRoundRect class is inherited from the GRect class.
+ */
+
+GRoundRect::GRoundRect(double width, double height) {
+ createGRoundRect(width, height, DEFAULT_CORNER);
+}
+
+GRoundRect::GRoundRect(double width, double height, double corner) {
+ createGRoundRect(width, height, corner);
+}
+
+GRoundRect::GRoundRect(double x, double y, double width, double height) {
+ createGRoundRect(width, height, DEFAULT_CORNER);
+ setLocation(x, y);
+}
+
+GRoundRect::GRoundRect(double x, double y, double width, double height,
+ double corner) {
+ createGRoundRect(width, height, corner);
+ setLocation(x, y);
+}
+
+GRoundRect::~GRoundRect() {
+ /* Empty */
+}
+
+string GRoundRect::getType() const {
+ return "GRoundRect";
+}
+
+string GRoundRect::toString() const {
+ ostringstream oss;
+ oss << "GRoundRect(" << x << ", " << y << ", "
+ << width << ", " << height << ", " << corner << ")";
+ return oss.str();
+}
+
+void GRoundRect::createGRoundRect(double width, double height, double corner) {
+ this->x = 0;
+ this->y = 0;
+ this->width = width;
+ this->height = height;
+ this->corner = corner;
+ fillFlag = false;
+ fillColor = "";
+ pp->createGRoundRect(this, width, height, corner);
+}
+
+/*
+ * Implementation notes: G3DRect class
+ * -----------------------------------
+ * Most of the G3DRect class is inherited from the GRect class.
+ */
+
+G3DRect::G3DRect(double width, double height) {
+ createG3DRect(width, height, false);
+}
+
+G3DRect::G3DRect(double width, double height, bool raised) {
+ createG3DRect(width, height, raised);
+}
+
+G3DRect::G3DRect(double x, double y, double width, double height) {
+ createG3DRect(width, height, false);
+ setLocation(x, y);
+}
+
+G3DRect::G3DRect(double x, double y, double width, double height,
+ bool raised) {
+ createG3DRect(width, height, raised);
+ setLocation(x, y);
+}
+
+G3DRect::~G3DRect() {
+ /* Empty */
+}
+
+void G3DRect::setRaised(bool raised) {
+ this->raised = raised;
+ pp->setRaised(this, raised);
+}
+
+bool G3DRect::isRaised() const {
+ return raised;
+}
+
+string G3DRect::getType() const {
+ return "G3DRect";
+}
+
+string G3DRect::toString() const {
+ ostringstream oss;
+ oss << boolalpha << "G3DRect(" << x << ", " << y << ", "
+ << width << ", " << height << ", " << raised << ")";
+ return oss.str();
+}
+
+void G3DRect::createG3DRect(double width, double height, bool raised) {
+ this->x = 0;
+ this->y = 0;
+ this->width = width;
+ this->height = height;
+ this->raised = raised;
+ fillFlag = false;
+ fillColor = "";
+ pp->createG3DRect(this, width, height, raised);
+}
+
+GOval::GOval(double width, double height) {
+ createGOval(width, height);
+}
+
+GOval::GOval(double x, double y, double width, double height) {
+ createGOval(width, height);
+ setLocation(x, y);
+}
+
+GOval::~GOval() {
+ /* Empty */
+}
+
+void GOval::setSize(const GDimension & size) {
+ setSize(size.getWidth(), size.getHeight());
+}
+
+void GOval::setSize(double width, double height) {
+ if (transformed) error("setSize: Object has been transformed");
+ this->width = width;
+ this->height = height;
+ pp->setSize(this, width, height);
+}
+
+void GOval::setBounds(const GRectangle & bounds) {
+ setLocation(bounds.getX(), bounds.getY());
+ setSize(bounds.getWidth(), bounds.getHeight());
+}
+
+void GOval::setBounds(double x, double y, double width, double height) {
+ setLocation(x, y);
+ setSize(width, height);
+}
+
+GRectangle GOval::getBounds() const {
+ if (transformed) return pp->getBounds(this);
+ return GRectangle(x, y, width, height);
+}
+
+bool GOval::contains(double x, double y) const {
+ if (transformed) return pp->contains(this, x, y);
+ double rx = width / 2;
+ double ry = height / 2;
+ if (rx == 0 || ry == 0) return false;
+ double dx = x - (this->x + rx);
+ double dy = y - (this->y + ry);
+ return (dx * dx) / (rx * rx) + (dy * dy) / (ry * ry) <= 1.0;
+}
+
+void GOval::setFilled(bool flag) {
+ fillFlag = true;
+ pp->setFilled(this, flag);
+}
+
+bool GOval::isFilled() const {
+ return fillFlag;
+}
+
+void GOval::setFillColor(string color) {
+ fillColor = color;
+ if (fillColor != "") {
+ fillColor = convertRGBToColor(convertColorToRGB(color));
+ }
+ pp->setFillColor(this, fillColor);
+}
+
+void GOval::setFillColor(int color) {
+ fillColor = convertRGBToColor(color);
+ pp->setFillColor(this, fillColor);
+}
+
+string GOval::getFillColor() const {
+ return fillColor;
+}
+
+string GOval::getType() const {
+ return "GOval";
+}
+
+string GOval::toString() const {
+ ostringstream oss;
+ oss << "GOval(" << x << ", " << y << ", "
+ << width << ", " << height << ")";
+ return oss.str();
+}
+
+void GOval::createGOval(double width, double height) {
+ this->x = 0;
+ this->y = 0;
+ this->width = width;
+ this->height = height;
+ fillFlag = false;
+ fillColor = "";
+ pp->createGOval(this, width, height);
+}
+
+/* GArc class */
+
+GArc::GArc(double width, double height, double start, double sweep) {
+ createGArc(width, height, start, sweep);
+}
+
+GArc::GArc(double x, double y, double width, double height,
+ double start, double sweep) {
+ createGArc(width, height, start, sweep);
+ setLocation(x, y);
+}
+
+void GArc::setStartAngle(double start) {
+ this->start = start;
+ pp->setStartAngle(this, start);
+}
+
+double GArc::getStartAngle() const {
+ return start;
+}
+
+void GArc::setSweepAngle(double sweep) {
+ this->sweep = sweep;
+ pp->setSweepAngle(this, sweep);
+}
+
+double GArc::getSweepAngle() const {
+ return sweep;
+}
+
+GPoint GArc::getStartPoint() const {
+ return getArcPoint(start);
+}
+
+GPoint GArc::getEndPoint() const {
+ return getArcPoint(start + sweep);
+}
+
+void GArc::setFrameRectangle(const GRectangle & rect) {
+ setFrameRectangle(rect.getX(), rect.getY(), rect.getWidth(),
+ rect.getHeight());
+}
+
+void GArc::setFrameRectangle(double x, double y, double width, double height) {
+ this->x = x;
+ this->y = y;
+ frameWidth = width;
+ frameHeight = height;
+ pp->setFrameRectangle(this, x, y, width, height);
+}
+
+GRectangle GArc::getFrameRectangle() const {
+ return GRectangle(0, 0, 0, 0);
+}
+
+void GArc::setFilled(bool flag) {
+ fillFlag = true;
+ pp->setFilled(this, flag);
+}
+
+bool GArc::isFilled() const {
+ return fillFlag;
+}
+
+void GArc::setFillColor(string color) {
+ fillColor = color;
+ if (fillColor != "") {
+ fillColor = convertRGBToColor(convertColorToRGB(color));
+ }
+ pp->setFillColor(this, fillColor);
+}
+
+void GArc::setFillColor(int color) {
+ fillColor = convertRGBToColor(color);
+ pp->setFillColor(this, fillColor);
+}
+
+string GArc::getFillColor() const {
+ return fillColor;
+}
+
+GRectangle GArc::getBounds() const {
+ if (transformed) return pp->getBounds(this);
+ double rx = frameWidth / 2;
+ double ry = frameHeight / 2;
+ double cx = x + rx;
+ double cy = y + ry;
+ double startRadians = start * PI / 180;
+ double sweepRadians = sweep * PI / 180;
+ double p1x = cx + cos(startRadians) * rx;
+ double p1y = cy - sin(startRadians) * ry;
+ double p2x = cx + cos(startRadians + sweepRadians) * rx;
+ double p2y = cy - sin(startRadians + sweepRadians) * ry;
+ double xMin = min(p1x, p2x);
+ double xMax = max(p1x, p2x);
+ double yMin = min(p1y, p2y);
+ double yMax = max(p1y, p2y);
+ if (containsAngle(0)) xMax = cx + rx;
+ if (containsAngle(90)) yMin = cy - ry;
+ if (containsAngle(180)) xMin = cx - rx;
+ if (containsAngle(270)) yMax = cy + ry;
+ if (isFilled()) {
+ xMin = min(xMin, cx);
+ yMin = min(yMin, cy);
+ xMax = max(xMax, cx);
+ yMax = max(yMax, cy);
+ }
+ return GRectangle(xMin, yMin, xMax - xMin, yMax - yMin);
+}
+
+bool GArc::contains(double x, double y) const {
+ if (transformed) return pp->contains(this, x, y);
+ double rx = frameWidth / 2;
+ double ry = frameHeight / 2;
+ if (rx == 0 || ry == 0) return false;
+ double dx = x - (this->x + rx);
+ double dy = y - (this->y + ry);
+ double r = (dx * dx) / (rx * rx) + (dy * dy) / (ry * ry);
+ if (fillFlag) {
+ if (r > 1.0) return false;
+ } else {
+ double t = ARC_TOLERANCE / ((rx + ry) / 2);
+ if (abs(1.0 - r) > t) return false;
+ }
+ return containsAngle(atan2(-dy, dx) * 180 / PI);
+}
+
+string GArc::getType() const {
+ return "GArc";
+}
+
+string GArc::toString() const {
+ ostringstream oss;
+ oss << "GArc(" << x << ", " << y << ", " << frameWidth << ", "
+ << frameHeight << ", " << start << ", " << sweep << ")";
+ return oss.str();
+}
+
+GPoint GArc::getArcPoint(double theta) const {
+ double rx = frameWidth / 2;
+ double ry = frameHeight / 2;
+ double cx = x + rx;
+ double cy = y + ry;
+ double radians = theta * PI / 180;
+ return GPoint(cx + rx * cos(radians), cy - ry * sin(radians));
+}
+
+bool GArc::containsAngle(double theta) const {
+ double start = min(this->start, this->start + this->sweep);
+ double sweep = abs(this->sweep);
+ if (sweep >= 360) return true;
+ theta = (theta < 0) ? 360 - fmod(-theta, 360) : fmod(theta, 360);
+ start = (start < 0) ? 360 - fmod(-start, 360) : fmod(start, 360);
+ if (start + sweep > 360) {
+ return theta >= start || theta <= start + sweep - 360;
+ } else {
+ return theta >= start && theta <= start + sweep;
+ }
+}
+
+void GArc::createGArc(double width, double height, double start, double sweep) {
+ this->x = 0;
+ this->y = 0;
+ frameWidth = width;
+ frameHeight = height;
+ this->start = start;
+ this->sweep = sweep;
+ fillFlag = false;
+ fillColor = "";
+ pp->createGArc(this, width, height, start, sweep);
+}
+
+GCompound::GCompound() {
+ pp->createGCompound(this);
+}
+
+void GCompound::add(GObject *gobj) {
+ pp->add(this, gobj);
+ contents.add(gobj);
+ gobj->parent = this;
+}
+
+void GCompound::add(GObject *gobj, double x, double y) {
+ gobj->setLocation(x, y);
+ add(gobj);
+}
+
+void GCompound::remove(GObject *gobj) {
+ int index = findGObject(gobj);
+ if (index != -1) removeAt(index);
+}
+
+void GCompound::removeAll() {
+ while (!contents.isEmpty()) {
+ removeAt(0);
+ }
+}
+
+int GCompound::getElementCount() {
+ return contents.size();
+}
+
+GObject *GCompound::getElement(int index) {
+ return contents.get(index);
+}
+
+GRectangle GCompound::getBounds() const {
+ if (transformed) return pp->getBounds(this);
+ double xMin = +1E20;
+ double yMin = +1E20;
+ double xMax = -1E20;
+ double yMax = -1E20;
+ for (int i = 0; i < contents.size(); i++) {
+ GRectangle bounds = contents.get(i)->getBounds();
+ xMin = min(xMin, bounds.getX());
+ yMin = min(yMin, bounds.getY());
+ xMax = max(xMax, bounds.getX());
+ yMin = min(yMax, bounds.getY());
+ }
+ return GRectangle(xMin, yMin, xMax - xMin, yMax - yMin);
+}
+
+bool GCompound::contains(double x, double y) const {
+ if (transformed) return pp->contains(this, x, y);
+ for (int i = 0; i < contents.size(); i++) {
+ if (contents.get(i)->contains(x, y)) return true;
+ }
+ return false;
+}
+
+string GCompound::getType() const {
+ return "GCompound";
+}
+
+string GCompound::toString() const {
+ return "GCompound(...)";
+}
+
+void GCompound::sendForward(GObject *gobj) {
+ int index = findGObject(gobj);
+ if (index == -1) return;
+ if (index != contents.size() - 1) {
+ contents.remove(index);
+ contents.insert(index + 1, gobj);
+ pp->sendForward(gobj);
+ }
+}
+
+void GCompound::sendToFront(GObject *gobj) {
+ int index = findGObject(gobj);
+ if (index == -1) return;
+ if (index != contents.size() - 1) {
+ contents.remove(index);
+ contents.add(gobj);
+ pp->sendToFront(gobj);
+ }
+}
+
+void GCompound::sendBackward(GObject *gobj) {
+ int index = findGObject(gobj);
+ if (index == -1) return;
+ if (index != 0) {
+ contents.remove(index);
+ contents.insert(index - 1, gobj);
+ pp->sendBackward(gobj);
+ }
+}
+
+void GCompound::sendToBack(GObject *gobj) {
+ int index = findGObject(gobj);
+ if (index == -1) return;
+ if (index != 0) {
+ contents.remove(index);
+ contents.insert(0, gobj);
+ pp->sendToBack(gobj);
+ }
+}
+
+int GCompound::findGObject(GObject *gobj) {
+ int n = contents.size();
+ for (int i = 0; i < n; i++) {
+ if (contents.get(i) == gobj) return i;
+ }
+ return -1;
+}
+
+void GCompound::removeAt(int index) {
+ GObject *gobj = contents[index];
+ contents.remove(index);
+ pp->remove(gobj);
+ gobj->parent = NULL;
+}
+
+GImage::GImage(string filename) {
+ createGImage(filename);
+}
+
+GImage::GImage(string filename, double x, double y) {
+ createGImage(filename);
+ setLocation(x, y);
+}
+
+GRectangle GImage::getBounds() const {
+ if (transformed) return pp->getBounds(this);
+ return GRectangle(x, y, width, height);
+}
+
+string GImage::getType() const {
+ return "GImage";
+}
+
+string GImage::toString() const {
+ return "GImage(\"" + filename + "\")";
+}
+
+void GImage::createGImage(string filename) {
+ this->filename = filename;
+ GDimension size = pp->createGImage(this, filename);
+ width = size.getWidth();
+ height = size.getHeight();
+}
+
+/*
+ * Implementation notes: GLabel class
+ * ----------------------------------
+ */
+
+GLabel::GLabel(string str) {
+ createGLabel(str);
+}
+
+GLabel::GLabel(string str, double x, double y) {
+ createGLabel(str);
+ setLocation(x, y);
+}
+
+void GLabel::createGLabel(const string & str) {
+ this->str = str;
+ pp->createGLabel(this, str);
+ setFont(DEFAULT_GLABEL_FONT);
+ GDimension size = pp->getGLabelSize(this);
+ width = size.getWidth();
+ height = size.getHeight();
+ ascent = pp->getFontAscent(this);
+ descent = pp->getFontDescent(this);
+}
+
+void GLabel::setFont(string font) {
+ this->font = font;
+ pp->setFont(this, font);
+ GDimension size = pp->getGLabelSize(this);
+ width = size.getWidth();
+ height = size.getHeight();
+ ascent = pp->getFontAscent(this);
+ descent = pp->getFontDescent(this);
+}
+
+string GLabel::getFont() const {
+ return font;
+}
+
+void GLabel::setLabel(string str) {
+ this->str = str;
+ pp->setLabel(this, str);
+ GDimension size = pp->getGLabelSize(this);
+ width = size.getWidth();
+ height = size.getHeight();
+}
+
+string GLabel::getLabel() const {
+ return str;
+}
+
+double GLabel::getFontAscent() const {
+ return ascent;
+}
+
+double GLabel::getFontDescent() const {
+ return descent;
+}
+
+GRectangle GLabel::getBounds() const {
+ if (transformed) return pp->getBounds(this);
+ return GRectangle(x, y - ascent, width, height);
+}
+
+string GLabel::getType() const {
+ return "GLabel";
+}
+
+string GLabel::toString() const {
+ return "GLabel(\"" + str + "\")";
+}
+
+/*
+ * Implementation notes: GLine class
+ * ---------------------------------
+ */
+
+GLine::GLine(double x0, double y0, double x1, double y1) {
+ pp->createGLine(this, x0, y0, x1, y1);
+ x = x0;
+ y = y0;
+ dx = x1 - x0;
+ dy = y1 - y0;
+}
+
+void GLine::setStartPoint(double x, double y) {
+ dx += this->x - x;
+ dy += this->y - y;
+ this->x = x;
+ this->y = y;
+ pp->setStartPoint(this, x, y);
+}
+
+GPoint GLine::getStartPoint() const {
+ return GPoint(x, y);
+}
+
+void GLine::setEndPoint(double x, double y) {
+ dx = x - this->x;
+ dy = y - this->y;
+ pp->setEndPoint(this, x, y);
+}
+
+GPoint GLine::getEndPoint() const {
+ return GPoint(x + dx, y + dy);
+}
+
+GRectangle GLine::getBounds() const {
+ if (transformed) return pp->getBounds(this);
+ double x0 = (dx < 0) ? x + dx : x;
+ double y0 = (dy < 0) ? y + dy : y;
+ return GRectangle(x0, y0, abs(dx), abs(dy));
+}
+
+bool GLine::contains(double x, double y) const {
+ if (transformed) return pp->contains(this, x, y);
+ double x0 = getX();
+ double y0 = getY();
+ double x1 = x0 + dx;
+ double y1 = y0 + dy;
+ double tSquared = LINE_TOLERANCE * LINE_TOLERANCE;
+ if (dsq(x, y, x0, y0) < tSquared) return true;
+ if (dsq(x, y, x1, y1) < tSquared) return true;
+ if (x < min(x0, x1) - LINE_TOLERANCE) return false;
+ if (x > max(x0, x1) + LINE_TOLERANCE) return false;
+ if (y < min(y0, y1) - LINE_TOLERANCE) return false;
+ if (y > max(y0, y1) + LINE_TOLERANCE) return false;
+ if ((float) (x0 - x1) == 0 && (float) (y0 - y1) == 0) return false;
+ double u = ((x - x0) * (x1 - x0) + (y - y0) * (y1 - y0))
+ / dsq(x0, y0, x1, y1);
+ return dsq(x, y, x0 + u * (x1 - x0), y0 + u * (y1 - y0)) < tSquared;
+}
+
+string GLine::getType() const {
+ return "GLine";
+}
+
+string GLine::toString() const {
+ ostringstream oss;
+ oss << "GLine(" << x << ", " << y << ", "
+ << (x + dx) << ", " << (y + dy) << ")";
+ return oss.str();
+}
+
+/*
+ * Implementation notes: GPolygon class
+ * ------------------------------------
+ */
+
+GPolygon::GPolygon() {
+ fillFlag = false;
+ fillColor = "";
+ pp->createGPolygon(this);
+}
+
+void GPolygon::addVertex(double x, double y) {
+ cx = x;
+ cy = y;
+ vertices.add(GPoint(cx, cy));
+ pp->addVertex(this, cx, cy);
+}
+
+void GPolygon::addEdge(double dx, double dy) {
+ addVertex(cx + dx, cy + dy);
+}
+
+void GPolygon::addPolarEdge(double r, double theta) {
+ addEdge(r * cos(theta * PI / 180), -r * sin(theta * PI / 180));
+}
+
+Vector<GPoint> GPolygon::getVertices() const {
+ return vertices;
+}
+
+void GPolygon::setFilled(bool flag) {
+ fillFlag = true;
+ pp->setFilled(this, flag);
+}
+
+bool GPolygon::isFilled() const {
+ return fillFlag;
+}
+
+void GPolygon::setFillColor(string color) {
+ fillColor = color;
+ if (fillColor != "") {
+ fillColor = convertRGBToColor(convertColorToRGB(color));
+ }
+ pp->setFillColor(this, fillColor);
+}
+
+void GPolygon::setFillColor(int rgb) {
+ fillColor = convertRGBToColor(rgb);
+ pp->setFillColor(this, fillColor);
+}
+
+string GPolygon::getFillColor() const {
+ return fillColor;
+}
+
+GRectangle GPolygon::getBounds() const {
+ if (transformed) return pp->getBounds(this);
+ double xMin = 0;
+ double yMin = 0;
+ double xMax = 0;
+ double yMax = 0;
+ for (int i = 0; i < vertices.size(); i++) {
+ double x = vertices[i].getX();
+ double y = vertices[i].getY();
+ if (i == 0 || x < xMin) xMin = x;
+ if (i == 0 || y < yMin) yMin = y;
+ if (i == 0 || x > xMax) xMax = x;
+ if (i == 0 || y > yMax) yMax = y;
+ }
+ return GRectangle(xMin, yMin, xMax - xMin, yMax - yMin);
+}
+
+bool GPolygon::contains(double x, double y) const {
+ if (transformed) return pp->contains(this, x, y);
+ int crossings = 0;
+ int n = vertices.size();
+ if (n < 2) return false;
+ if (vertices[0] == vertices[n - 1]) n--;
+ double x0 = vertices[0].getX();
+ double y0 = vertices[0].getY();
+ for (int i = 1; i <= n; i++) {
+ double x1 = vertices[i % n].getX();
+ double y1 = vertices[i % n].getY();
+ if ((y0 > y) != (y1 > y) && x - x0 < (x1 - x0) * (y - y0) / (y1 - y0)) {
+ crossings++;
+ }
+ x0 = x1;
+ y0 = y1;
+ }
+ return (crossings % 2 == 1);
+}
+
+string GPolygon::getType() const {
+ return "GPolygon";
+}
+
+string GPolygon::toString() const {
+ ostringstream oss;
+ oss << "GPolygon(" << vertices.size() << " vertices)";
+ return oss.str();
+}
+
+static double dsq(double x0, double y0, double x1, double y1) {
+ return (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
+}
diff --git a/labb8/lib/StanfordCPPLib/gobjects.h b/labb8/lib/StanfordCPPLib/gobjects.h
new file mode 100755
index 0000000..f0637bf
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gobjects.h
@@ -0,0 +1,1491 @@
+/*
+ * File: gobjects.h
+ * ----------------
+ * This file exports a hierarchy of graphical shapes based on
+ * the model developed for the ACM Java Graphics.
+ * <include src="pictures/ClassHierarchies/GObjectHierarchy-h.html">
+ */
+
+#ifndef _gobjects_h
+#define _gobjects_h
+
+#include "gtypes.h"
+#include "gwindow.h"
+#include "vector.h"
+
+class GCompound;
+
+/*
+ * Class: GObject
+ * --------------
+ * This class is the common superclass of all graphical objects that can
+ * be displayed on a graphical window. The class <code>GObject</code>
+ * itself is an <b><i>abstract class</i></b>, which means that you are not
+ * allowed to construct a <code>GObject</code> directly but must instead
+ * construct one of the concrete subclasses.
+ * <include src="pictures/ClassHierarchies/GObjectHierarchy.html">
+ *
+ * <p>Most methods used for graphics take a pointer to a <code>GObject</code>
+ * rather than the <code>GObject</code> itself. Applications that use
+ * <code>GObject</code> pointers therefore use the arrow operator
+ * (<code>-&gt;</code>) to apply methods to the object pointer.
+ * For examples illustrating the use of the <code>GObject</code> class, see
+ * the descriptions of the individual subclasses.
+ */
+
+class GObject {
+
+public:
+
+/*
+ * Destructor: ~GObject
+ * --------------------
+ * Frees the storage for the object.
+ */
+
+ virtual ~GObject();
+
+/*
+ * Method: getX
+ * Usage: double x = gobj->getX();
+ * -------------------------------
+ * Returns the <i>x</i>-coordinate of the object.
+ */
+
+ double getX() const;
+
+/*
+ * Method: getY
+ * Usage: double y = gobj->getY();
+ * -------------------------------
+ * Returns the <i>y</i>-coordinate of the object.
+ */
+
+ double getY() const;
+
+/*
+ * Method: getLocation
+ * Usage: GPoint pt = gobj->getLocation();
+ * ---------------------------------------
+ * Returns the location of this object as a <code>GPoint</code>.
+ */
+
+ GPoint getLocation() const;
+
+/*
+ * Method: setLocation
+ * Usage: gobj->setLocation(pt);
+ * gobj->setLocation(x, y);
+ * -------------------------------
+ * Sets the location of this object to the specified point.
+ */
+
+ void setLocation(const GPoint & pt);
+ void setLocation(double x, double y);
+
+/*
+ * Method: move
+ * Usage: gobj->move(dx, dy);
+ * --------------------------
+ * Moves the object on the screen using the displacements
+ * <code>dx</code> and <code>dy</code>.
+ */
+
+ void move(double dx, double dy);
+
+/*
+ * Method: getWidth
+ * Usage: double width = gobj->getWidth();
+ * ---------------------------------------
+ * Returns the width of this object, which is defined to be the width of
+ * the bounding box.
+ */
+
+ double getWidth() const;
+
+/*
+ * Method: getHeight
+ * Usage: double height = gobj->getHeight();
+ * -----------------------------------------
+ * Returns the height of this object, which is defined to be the height
+ * of the bounding box.
+ */
+
+ double getHeight() const;
+
+/*
+ * Method: getSize
+ * Usage: GDimension size = gobj->getSize();
+ * -----------------------------------------
+ * Returns the size of the object as a <code>GDimension</code>.
+ */
+
+ GDimension getSize() const;
+
+/*
+ * Method: getBounds
+ * Usage: GRectangle rect = gobj->getBounds();
+ * -------------------------------------------
+ * Returns the bounding box of this object, which is defined to be the
+ * smallest rectangle that covers everything drawn by the figure. The
+ * coordinates of this rectangle do not necessarily match the location
+ * returned by <code>getLocation</code>. Given a <code>GLabel</code>
+ * object, for example, <code>getLocation</code> returns the coordinates
+ * of the point on the baseline at which the string begins; the
+ * <code>getBounds</code> method, by contrast, returns a rectangle that
+ * covers the entire window area occupied by the string.
+ */
+
+ virtual GRectangle getBounds() const = 0;
+
+/*
+ * Method: setLineWidth
+ * Usage: gobj->setLineWidth(lineWidth);
+ * -------------------------------------
+ * Sets the width of the line used to draw this object.
+ */
+
+ void setLineWidth(double lineWidth);
+
+/*
+ * Method: getLineWidth
+ * Usage: double lineWidth = gobj->getLineWidth();
+ * -----------------------------------------------
+ * Returns the width of the line used to draw this object.
+ */
+
+ double getLineWidth() const;
+
+/*
+ * Method: setColor
+ * Usage: gobj->setColor(color);
+ * -----------------------------
+ * Sets the color used to display this object. The <code>color</code>
+ * string is usually one of the predefined color names:
+ *
+ * <code>BLACK</code>,
+ * <code>BLUE</code>,
+ * <code>CYAN</code>,
+ * <code>DARK_GRAY</code>,
+ * <code>GRAY</code>,
+ * <code>GREEN</code>,
+ * <code>LIGHT_GRAY</code>,
+ * <code>MAGENTA</code>,
+ * <code>ORANGE</code>,
+ * <code>PINK</code>,
+ * <code>RED</code>,
+ * <code>WHITE</code>, and
+ * <code>YELLOW</code>.
+ *
+ * The case of the individual letters in the color name is ignored, as
+ * are spaces and underscores, so that the color <code>DARK_GRAY</code>
+ * can be written as <code>"Dark Gray"</code>.
+ *
+ * <p>The color can also be specified as a string in the form
+ * <code>"#rrggbb"</code> where <code>rr</code>, <code>gg</code>, and
+ * <code>bb</code> are pairs of hexadecimal digits indicating the
+ * red, green, and blue components of the color, respectively.
+ */
+
+ void setColor(std::string color);
+ void setColor(int rgb);
+
+/*
+ * Method: getColor
+ * Usage: string color = gobj->getColor();
+ * ---------------------------------------
+ * Returns the color used to display this object. This color is
+ * always returned as a string in the form <code>"#rrggbb"</code>,
+ * where <code>rr</code>, <code>gg</code>, and <code>bb</code> are
+ * the red, green, and blue components of the color, expressed as
+ * two-digit hexadecimal values.
+ */
+
+ std::string getColor() const;
+
+/*
+ * Method: scale
+ * Usage: gobj->scale(sf);
+ * gobj->scale(sx, sy);
+ * ---------------------------
+ * Scales the object by the specified scale factors. Most clients will use
+ * the first form, which scales the object by <code>sf</code> in both
+ * dimensions, so that invoking <code>gobj->scale(2)</code> doubles the
+ * size of the object. The second form applies independent scale factors
+ * to the <i>x</i> and <i>y</i> dimensions.
+ */
+
+ void scale(double sf);
+ void scale(double sx, double sy);
+
+/*
+ * Method: rotate
+ * Usage: gobj->rotate(theta);
+ * ---------------------------
+ * Transforms the object by rotating it <code>theta</code> degrees
+ * counterclockwise around its origin.
+ */
+
+ void rotate(double theta);
+
+/*
+ * Method: setVisible
+ * Usage: gobj->setVisible(flag);
+ * ------------------------------
+ * Sets whether this object is visible.
+ */
+
+ void setVisible(bool flag);
+
+/*
+ * Method: isVisible
+ * Usage: if (gobj->isVisible()) ...
+ * ---------------------------------
+ * Returns <code>true</code> if this object is visible.
+ */
+
+ bool isVisible() const;
+
+/*
+ * Method: sendForward
+ * Usage: gobj->sendForward();
+ * ---------------------------
+ * Moves this object one step toward the front in the <i>z</i> dimension.
+ * If it was already at the front of the stack, nothing happens.
+ */
+
+ void sendForward();
+
+/*
+ * Method: sendToFront
+ * Usage: gobj->sendToFront();
+ * ---------------------------
+ * Moves this object to the front of the display in the <i>z</i> dimension.
+ * By moving it to the front, this object will appear to be on top of the
+ * other graphical objects on the display and may hide any objects that
+ * are further back.
+ */
+
+ void sendToFront();
+
+/*
+ * Method: sendBackward
+ * Usage: gobj->sendBackward();
+ * ----------------------------
+ * Moves this object one step toward the back in the <i>z</i> dimension.
+ * If it was already at the back of the stack, nothing happens.
+ */
+
+ void sendBackward();
+
+/*
+ * Method: sendToBack
+ * Usage: gobj->sendToBack();
+ * --------------------------
+ * Moves this object to the back of the display in the <i>z</i> dimension.
+ * By moving it to the back, this object will appear to be behind the other
+ * graphical objects on the display and may be obscured by other objects
+ * in front.
+ */
+
+ void sendToBack();
+
+/*
+ * Method: contains
+ * Usage: if (gobj->contains(pt)) ...
+ * if (gobj->contains(x, y)) ...
+ * ------------------------------------
+ * Returns <code>true</code> if the specified point is inside the object.
+ */
+
+ bool contains(GPoint pt) const;
+ virtual bool contains(double x, double y) const;
+
+/*
+ * Method: getType
+ * Usage: string type = gobj->getType();
+ * -------------------------------------
+ * Returns the concrete type of the object as a string, as in
+ * <code>"GOval"</code> or <code>"GRect"</code>.
+ */
+
+ virtual std::string getType() const = 0;
+
+/*
+ * Method: toString
+ * Usage: gobj->toString();
+ * ------------------------
+ * Returns a printable representation of the object.
+ */
+
+ virtual std::string toString() const = 0;
+
+/*
+ * Method: getParent
+ * Usage: GCompound *parent = gobj->getParent();
+ * ---------------------------------------------
+ * Returns a pointer to the <code>GCompound</code> that contains this
+ * object. Every <code>GWindow</code> is initialized to contain a single
+ * <code>GCompound</code> that is aligned with the window. Adding
+ * objects to the window adds them to that <code>GCompound</code>,
+ * which means that every object you add to the window has a parent.
+ * Calling <code>getParent</code> on the top-level <code>GCompound</code>
+ * returns <code>NULL</code>.
+ */
+
+ GCompound *getParent() const;
+
+/* Private section */
+
+private:
+ const GObject & operator=(const GObject &) { return *this; }
+ GObject(const GObject &) { }
+
+/* Instance variables */
+
+protected:
+ double x; /* The x coordinate of the origin */
+ double y; /* The y coordinate of the origin */
+ double lineWidth; /* The width of the line in pixels */
+ std::string color; /* The color of the object */
+ bool visible; /* Indicates if object is visible */
+ bool transformed; /* Indicates if object is transformed */
+ GCompound *parent; /* Pointer to the parent */
+
+protected:
+ GObject();
+
+ friend class GArc;
+ friend class GButton;
+ friend class GCheckBox;
+ friend class GChooser;
+ friend class GCompound;
+ friend class GImage;
+ friend class GInteractor;
+ friend class GLabel;
+ friend class GLine;
+ friend class GOval;
+ friend class GPolygon;
+ friend class GRect;
+ friend class GRoundRect;
+ friend class GSlider;
+ friend class GTextField;
+ friend class G3DRect;
+
+};
+
+/*
+ * Class: GRect
+ * ------------
+ * This class represents a graphical object whose appearance consists of
+ * a rectangular box. For example, the following code adds a filled, red
+ * <nobr>200<font class=sansserif size=-1>x</font>100</nobr> rectangle
+ * at the upper left corner of the graphics window:
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * cout << "This program draws a red rectangle at (0, 0)." << endl;
+ * GRect *rect = new GRect(0, 0, 200, 100);
+ * rect->setFilled(true);
+ * rect->setColor("RED");
+ * gw.add(rect);
+ * return 0;
+ * }
+ *</pre>
+ */
+
+class GRect : public GObject {
+
+public:
+
+/*
+ * Constructor: GRect
+ * Usage: GRect *rect = new GRect(width, height);
+ * GRect *rect = new GRect(x, y, width, height);
+ * ----------------------------------------------------
+ * Constructs a rectangle with the specified width and height. The first
+ * form is positioned at the origin; the second at the coordinates
+ * given by <code>x</code> and <code>y</code>.
+ */
+
+ GRect(double width, double height);
+ GRect(double x, double y, double width, double height);
+
+/*
+ * Destructor: ~GRect
+ * ------------------
+ * Frees any resources maintained by this object.
+ */
+
+ virtual ~GRect();
+
+/*
+ * Method: setSize
+ * Usage: rect->setSize(size);
+ * rect->setSize(width, height);
+ * ------------------------------------
+ * Changes the size of this rectangle to the specified width and height.
+ */
+
+ void setSize(const GDimension & size);
+ void setSize(double width, double height);
+
+/*
+ * Method: setBounds
+ * Usage: rect->setBounds(rect);
+ * rect->setBounds(x, y, width, height);
+ * --------------------------------------------
+ * Changes the bounds of this rectangle to the specified values.
+ */
+
+ void setBounds(const GRectangle & size);
+ void setBounds(double x, double y, double width, double height);
+
+/*
+ * Method: setFilled
+ * Usage: rect->setFilled(flag);
+ * -----------------------------
+ * Sets the fill status for the rectangle, where <code>false</code> is
+ * outlined and <code>true</code> is filled.
+ */
+
+ void setFilled(bool flag);
+
+/*
+ * Method: isFilled
+ * Usage: if (rect->isFilled()) ...
+ * --------------------------------
+ * Returns <code>true</code> if the rectangle is filled.
+ */
+
+ bool isFilled() const;
+
+/*
+ * Method: setFillColor
+ * Usage: rect->setFillColor(color);
+ * ---------------------------------
+ * Sets the color used to display the filled region of this rectangle.
+ */
+
+ void setFillColor(std::string color);
+ void setFillColor(int rgb);
+
+/*
+ * Method: getFillColor
+ * Usage: string color = rect->getFillColor();
+ * -------------------------------------------
+ * Returns the color used to display the filled region of this rectangle. If
+ * none has been set, <code>getFillColor</code> returns the empty string.
+ */
+
+ std::string getFillColor() const;
+
+/* Prototypes for the virtual methods */
+
+ virtual GRectangle getBounds() const;
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+protected:
+
+/* Instance variables */
+
+ double width; /* The width of the rectangle */
+ double height; /* The height of the rectangle */
+ bool fillFlag; /* Indicates whether the object is filled */
+ std::string fillColor; /* Color used to fill the object */
+
+/* Protected methods */
+
+ GRect();
+ virtual void createGRect(double width, double height);
+
+};
+
+/*
+ * Class: GRoundRect
+ * -----------------
+ * This class represents a graphical object whose appearance consists
+ * of a rectangular box with rounded corners.
+ */
+
+class GRoundRect : public GRect {
+
+public:
+
+/*
+ * Constructor: GRoundRect
+ * Usage: GRoundRect *rect = new GRoundRect(width, height);
+ * GRoundRect *rect = new GRoundRect(width, height, corner);
+ * GRoundRect *rect = new GRoundRect(x, y, width, height);
+ * GRoundRect *rect = new GRoundRect(x, y, width, height, corner);
+ * ----------------------------------------------------------------------
+ * Constructs a new rectangle with the specified width and height. If
+ * the <code>x</code> and <code>y</code> parameters are specified, they
+ * are used to specify the origin. The <code>corner</code> parameter
+ * specifies the diameter of the arc forming the corner.
+ */
+
+ GRoundRect(double width, double height);
+ GRoundRect(double width, double height, double corner);
+ GRoundRect(double x, double y, double width, double height);
+ GRoundRect(double x, double y, double width, double height, double corner);
+
+/*
+ * Destructor: ~GRoundRect
+ * -----------------------
+ * Frees any resources maintained by this object.
+ */
+
+ virtual ~GRoundRect();
+
+/* Prototypes for the virtual methods */
+
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+protected:
+
+ double corner;
+
+/* Protected methods */
+
+ void createGRoundRect(double width, double height, double corner);
+
+};
+
+/*
+ * Class: G3DRect
+ * --------------
+ * This graphical object subclass represents a rectangular box that can
+ * be raised or lowered.
+ */
+
+class G3DRect : public GRect {
+
+public:
+
+/*
+ * Constructor: G3DRect
+ * Usage: G3DRect *rect = new G3DRect(width, height);
+ * G3DRect *rect = new G3DRect(width, height, raised);
+ * G3DRect *rect = new G3DRect(x, y, width, height);
+ * G3DRect *rect = new G3DRect(x, y, width, height, raised);
+ * ----------------------------------------------------------------
+ * Constructs a new 3D rectangle with the specified width and height. If
+ * the <code>x</code> and <code>y</code> parameters are specified, they
+ * are used to specify the origin. The <code>raised</code> parameter
+ * determines whether the rectangle should be drawn with highlights that
+ * suggest that it is raised about the background.
+ */
+
+ G3DRect(double width, double height);
+ G3DRect(double width, double height, bool raised);
+ G3DRect(double x, double y, double width, double height);
+ G3DRect(double x, double y, double width, double height, bool raised);
+
+/*
+ * Destructor: ~G3DRect
+ * --------------------
+ * Frees any resources maintained by this object.
+ */
+
+ virtual ~G3DRect();
+
+/*
+ * Method: setRaised
+ * Usage: rect->setRaised(raised);
+ * -------------------------------
+ * Indicates whether this object appears raised.
+ */
+
+ void setRaised(bool raised);
+
+/*
+ * Method: isRaised
+ * Usage: if (rect->isRaised()) ...
+ * --------------------------------
+ * Returns <code>true</code> if this object appears raised.
+ */
+
+ bool isRaised() const;
+
+/* Prototypes for the virtual methods */
+
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+protected:
+
+ bool raised;
+
+/* Protected methods */
+
+ void createG3DRect(double width, double height, bool raised);
+
+};
+
+/*
+ * Class: GOval
+ * ------------
+ * This graphical object subclass represents an oval inscribed in
+ * a rectangular box. For example, the following code displays a
+ * filled green oval inscribed in the graphics window:
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * cout << "This program draws a green oval filling the window." << endl;
+ * GOval *oval = new GOval(gw.getWidth(), gw.getHeight());
+ * oval->setFilled(true);
+ * oval->setColor("GREEN");
+ * gw.add(oval);
+ * return 0;
+ * }
+ *</pre>
+ */
+
+class GOval : public GObject {
+
+public:
+
+/*
+ * Constructor: GOval
+ * Usage: GOval *oval = new GOval(width, height);
+ * GOval *oval = new GOval(x, y, width, height);
+ * ----------------------------------------------------
+ * Constructs a new oval inscribed in the specified rectangle. The
+ * first form is positioned at the origin; the second at the coordinates
+ * given by <code>x</code> and <code>y</code>.
+ */
+
+ GOval(double width, double height);
+ GOval(double x, double y, double width, double height);
+
+/*
+ * Destructor: ~GOval
+ * ------------------
+ * Frees any resources maintained by this object.
+ */
+
+ virtual ~GOval();
+
+/*
+ * Method: setSize
+ * Usage: oval->setSize(size);
+ * oval->setSize(width, height);
+ * ------------------------------------
+ * Changes the size of the bounding rectangle to the specified width
+ * and height.
+ */
+
+ void setSize(const GDimension & size);
+ void setSize(double width, double height);
+
+/*
+ * Method: setBounds
+ * Usage: oval->setBounds(rect);
+ * oval->setBounds(x, y, width, height);
+ * --------------------------------------------
+ * Changes the bounds of the oval to the specified values.
+ */
+
+ void setBounds(const GRectangle & size);
+ void setBounds(double x, double y, double width, double height);
+
+/*
+ * Method: setFilled
+ * Usage: oval->setFilled(flag);
+ * -----------------------------
+ * Sets the fill status for the oval, where <code>false</code> is
+ * outlined and <code>true</code> is filled.
+ */
+
+ void setFilled(bool flag);
+
+/*
+ * Method: isFilled
+ * Usage: if (oval->isFilled()) ...
+ * --------------------------------
+ * Returns <code>true</code> if the oval is filled.
+ */
+
+ bool isFilled() const;
+
+/*
+ * Method: setFillColor
+ * Usage: oval->setFillColor(color);
+ * ---------------------------------
+ * Sets the color used to display the filled region of this oval.
+ */
+
+ void setFillColor(std::string color);
+ void setFillColor(int rgb);
+
+/*
+ * Method: getFillColor
+ * Usage: string color = oval->getFillColor();
+ * -------------------------------------------
+ * Returns the color used to display the filled region of this oval. If
+ * none has been set, <code>getFillColor</code> returns the empty string.
+ */
+
+ std::string getFillColor() const;
+
+/* Prototypes for the virtual methods */
+
+ virtual GRectangle getBounds() const;
+ virtual bool contains(double x, double y) const;
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+protected:
+
+/* Instance variables */
+
+ double width; /* The width of the bounding rectangle */
+ double height; /* The height of the bounding rectangle */
+ bool fillFlag; /* Indicates whether the object is filled */
+ std::string fillColor; /* Color used to fill the object */
+
+/* Protected methods */
+
+ void createGOval(double width, double height);
+
+};
+
+/*
+ * Class: GArc
+ * -----------
+ * This graphical object subclass represents an elliptical arc. The
+ * arc is specified by the following parameters:
+ *
+ * <p><ul>
+ * <li>The coordinates of the bounding rectangle (<code>x</code>,
+ * <code>y</code>, <code>width</code>, <code>height</code>)
+ * <li>The angle at which the arc starts (<code>start</code>)
+ * <li>The number of degrees that the arc covers (<code>sweep</code>)
+ * </ul>
+ *
+ * <p>All angles in a <code>GArc</code> description are measured in
+ * degrees moving counterclockwise from the +<i>x</i> axis. Negative
+ * values for either <code>start</code> or <code>sweep</code> indicate
+ * motion in a clockwise direction.
+ * <include src="pictures/GObjectDiagrams/GArcGeometry.html">
+ */
+
+class GArc : public GObject {
+
+public:
+
+/*
+ * Constructor: GArc
+ * Usage: GArc *arc = new GArc(width, height, start, sweep);
+ * GArc *arc = new GArc(x, y, width, height, start, sweep);
+ * ---------------------------------------------------------------
+ * Creates a new <code>GArc</code> object consisting of an elliptical arc.
+ * The first form creates a <code>GArc</code> whose origin is the point
+ * (0,&nbsp;0); the second form positions the <code>GArc</code> at the
+ * point (<code>x</code>, <code>y</code>).
+ * <include src="pictures/GObjectDiagrams/GArcExamples.html">
+ */
+
+ GArc(double width, double height, double start, double sweep);
+ GArc(double x, double y, double width, double height,
+ double start, double sweep);
+
+/*
+ * Method: setStartAngle
+ * Usage: arc->setStartAngle(start);
+ * ---------------------------------
+ * Sets the starting angle for this <code>GArc</code> object.
+ */
+
+ void setStartAngle(double start);
+
+/*
+ * Method: getStartAngle
+ * Usage: double angle = arc->getStartAngle();
+ * -------------------------------------------
+ * Returns the starting angle for this <code>GArc</code> object.
+ */
+
+ double getStartAngle() const;
+
+/*
+ * Method: setSweepAngle
+ * Usage: arc->setSweepAngle(start);
+ * ---------------------------------
+ * Sets the sweep angle for this <code>GArc</code> object.
+ */
+
+ void setSweepAngle(double start);
+
+/*
+ * Method: getSweepAngle
+ * Usage: double angle = arc->getSweepAngle();
+ * -------------------------------------------
+ * Returns the sweep angle for this <code>GArc</code> object.
+ */
+
+ double getSweepAngle() const;
+
+/*
+ * Method: getStartPoint
+ * Usage: GPoint pt = arc->getStartPoint();
+ * ----------------------------------------
+ * Returns the point at which the arc starts.
+ */
+
+ GPoint getStartPoint() const;
+
+/*
+ * Method: getEndPoint
+ * Usage: GPoint pt = arc->getEndPoint();
+ * --------------------------------------
+ * Returns the point at which the arc ends.
+ */
+
+ GPoint getEndPoint() const;
+
+/*
+ * Method: setFrameRectangle
+ * Usage: arc->setFrameRectangle(rect);
+ * arc->setFrameRectangle(x, y, width, height);
+ * ---------------------------------------------------
+ * Changes the boundaries of the rectangle used to frame the arc.
+ */
+
+ void setFrameRectangle(const GRectangle & rect);
+ void setFrameRectangle(double x, double y, double width, double height);
+
+/*
+ * Method: getFrameRectangle
+ * Usage: GRectangle rect = arc->getFrameRectangle();
+ * --------------------------------------------------
+ * Returns the boundaries of the rectangle used to frame the arc.
+ */
+
+ GRectangle getFrameRectangle() const;
+
+/*
+ * Method: setFilled
+ * Usage: arc->setFilled(flag);
+ * ----------------------------
+ * Sets the fill status for the arc, where <code>false</code> is
+ * outlined and <code>true</code> is filled. If a <code>GArc</code> is
+ * unfilled, the figure consists only of the arc itself. If a
+ * <code>GArc</code> is filled, the figure consists of the
+ * pie-shaped wedge formed by connecting the endpoints of the arc to
+ * the center. As an example, the following program draws a 270-degree
+ * arc starting at 45 degrees, filled in yellow, much like the character
+ * in the PacMan video game:
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * cout << "This program draws the PacMan character." << endl;
+ * double cx = gw.getWidth() / 2;
+ * double cy = gw.getHeight() / 2;
+ * double r = 25;
+ * GArc *pacman = new GArc(cx - r, cy - r, 2 * r, 2 * r, 45, 270);
+ * pacman->setFilled(true);
+ * pacman->setFillColor("YELLOW");
+ * gw.add(pacman);
+ * return 0;
+ * }
+ *</pre>
+ * <include src="pictures/GObjectDiagrams/PacMan.html">
+ */
+
+ void setFilled(bool flag);
+
+/*
+ * Method: isFilled
+ * Usage: if (arc->isFilled()) ...
+ * -------------------------------
+ * Returns <code>true</code> if the arc is filled.
+ */
+
+ bool isFilled() const;
+
+/*
+ * Method: setFillColor
+ * Usage: arc->setFillColor(color);
+ * --------------------------------
+ * Sets the color used to display the filled region of this arc.
+ * Colors are specified as strings as described in the notes for the
+ * <a href="GObject-class.html#Method:setColor"><code>setColor</code></a>
+ * method.
+ */
+
+ void setFillColor(std::string color);
+ void setFillColor(int rgb);
+
+/*
+ * Method: getFillColor
+ * Usage: string color = arc->getFillColor();
+ * ------------------------------------------
+ * Returns the color used to display the filled region of this arc. If
+ * none has been set, <code>getFillColor</code> returns the empty string.
+ */
+
+ std::string getFillColor() const;
+
+/* Prototypes for the virtual methods */
+
+ virtual GRectangle getBounds() const;
+ virtual bool contains(double x, double y) const;
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+private:
+
+ GPoint getArcPoint(double theta) const;
+ bool containsAngle(double theta) const;
+ void createGArc(double width, double height, double start, double sweep);
+
+/* Instance variables */
+
+ double start; /* Starting angle of the arc */
+ double sweep; /* How many degrees the arc runs */
+ double frameWidth; /* The width of the bounding box */
+ double frameHeight; /* The height of the bounding box */
+ std::string fillColor; /* The color of the interior */
+ bool fillFlag; /* Indicates if the arc is filled */
+
+};
+
+/*
+ * Class: GCompound
+ * ----------------
+ * This graphical object subclass consists of a collection
+ * of other graphical objects. Once assembled, the internal objects
+ * can be manipulated as a unit. The <code>GCompound</code> keeps
+ * track of its own position, and all items within it are drawn
+ * relative to that location.
+ */
+
+class GCompound : public GObject {
+
+public:
+
+/*
+ * Constructor: GCompound
+ * Usage: GCompound *comp = new GCompound();
+ * -----------------------------------------
+ * Creates a <code>GCompound</code> object with no internal components.
+ */
+
+ GCompound();
+
+/*
+ * Method: add
+ * Usage: comp->add(gobj);
+ * comp->add(gobj, x, y);
+ * -----------------------------
+ * Adds a new graphical object to the <code>GCompound</code>. The second
+ * form moves the object to the point (<code>x</code>, <code>y</code>) first.
+ */
+
+ void add(GObject *gobj);
+ void add(GObject *gobj, double x, double y);
+
+/*
+ * Method: remove
+ * Usage: comp->remove(gobj);
+ * --------------------------
+ * Removes the specified object from the <code>GCompound</code>.
+ */
+
+ void remove(GObject *gobj);
+
+/*
+ * Method: removeAll
+ * Usage: comp->removeAll();
+ * -------------------------
+ * Removes all graphical objects from the <code>GCompound</code>.
+ */
+
+ void removeAll();
+
+/*
+ * Method: getElementCount
+ * Usage: int n = comp->getElementCount();
+ * ---------------------------------------
+ * Returns the number of graphical objects stored in the
+ * <code>GCompound</code>.
+ */
+
+ int getElementCount();
+
+/*
+ * Method: getElement
+ * Usage: GObject *gobj = comp->getElement(index);
+ * -----------------------------------------------
+ * Returns a pointer to the graphical object at the specified index,
+ * numbering from back to front in the the <i>z</i> dimension.
+ */
+
+ GObject *getElement(int index);
+
+/* Prototypes for the virtual methods */
+
+ virtual GRectangle getBounds() const;
+ virtual bool contains(double x, double y) const;
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+private:
+ void sendForward(GObject *gobj);
+ void sendToFront(GObject *gobj);
+ void sendBackward(GObject *gobj);
+ void sendToBack(GObject *gobj);
+ int findGObject(GObject *gobj);
+ void removeAt(int index);
+
+/* Instance variables */
+
+ Vector<GObject *> contents;
+
+/* Friend declarations */
+
+ friend class GObject;
+
+};
+
+/*
+ * Class: GImage
+ * -------------
+ * This graphical object subclass represents an image from a file.
+ * For example, the following code displays a <code>GImage</code>
+ * containing the Stanford tree at the center of the window, assuming
+ * that the image file <code>StanfordTree.png</code> exists, either in
+ * the current directory or an <code>images</code> subdirectory:
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * cout << "This program draws the Stanford tree." << endl;
+ * GImage *tree = new GImage("StanfordTree.png");
+ * double x = (gw.getWidth() - tree->getWidth()) / 2;
+ * double y = (gw.getHeight() - tree->getHeight()) / 2;
+ * gw.add(tree, x, y);
+ * return 0;
+ * }
+ *</pre>
+ */
+
+class GImage : public GObject {
+
+public:
+
+/*
+ * Constructor: GImage
+ * Usage: GImage *image = new GImage(filename);
+ * GImage *image = new GImage(filename, x, y);
+ * --------------------------------------------------
+ * Constructs a new image by loading the image from the specified
+ * file, which is either in the current directory or a subdirectory named
+ * <code>images</code>. By default, the upper left corner of the image
+ * appears at the origin; the second form automatically sets the location
+ * to the point (<code>x</code>, <code>y</code>).
+ */
+
+ GImage(std::string filename);
+ GImage(std::string filename, double x, double y);
+
+/* Prototypes for the virtual methods */
+
+ virtual GRectangle getBounds() const;
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+private:
+ std::string filename;
+ double width;
+ double height;
+
+ void createGImage(std::string filename);
+
+};
+
+/*
+ * Class: GLabel
+ * -------------
+ * This graphical object subclass represents a text string. For
+ * example, the following code adds a <code>GLabel</code> containing
+ * the string <code>"hello, world"</code> to the center of the window:
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * cout << "This program draws the 'hello, world' message." << endl;
+ * GLabel *label = new GLabel("hello, world");
+ * label->setFont("SansSerif-18");
+ * double x = (gw.getWidth() - label->getWidth()) / 2;
+ * double y = (gw.getHeight() + label->getFontAscent()) / 2;
+ * gw.add(label, x, y);
+ * return 0;
+ * }
+ *</pre>
+ *
+ * Controlling the appearance and positioning of a <code>GLabel</code>
+ * depends on understanding the following terms:
+ *
+ * <p><ul>
+ * <li>The <b><i>baseline</i></b> is the horizontal line on which the
+ * characters rest.
+ * <li>The <b><i>origin</i></b> is the point on the baseline at which
+ * the label begins.
+ * <li>The <b><i>height</i></b> is the distance that separate two
+ * successive lines.
+ * <li>The <b><i>ascent</i></b> is the maximum distance a character
+ * in this font extends above the baseline.
+ * <li>The <b><i>descent</i></b> is the maximum distance a character
+ * in this font extends below the baseline.
+ * </ul>
+ * <include src="pictures/GObjectDiagrams/GLabelGeometry.html">
+ */
+
+class GLabel : public GObject {
+
+public:
+
+/*
+ * Constructor: GLabel
+ * Usage: GLabel *label = new GLabel(str);
+ * GLabel *label = new GLabel(str, x, y);
+ * ---------------------------------------------
+ * Creates a <code>GLabel</code> object containing the specified string.
+ * By default, the baseline of the first character appears at the origin;
+ * the second form automatically resets the location of the
+ * <code>GLabel</code> to the point (<code>x</code>, <code>y</code>).
+ */
+
+ GLabel(std::string str);
+ GLabel(std::string str, double x, double y);
+
+/*
+ * Method: setFont
+ * Usage: label->setFont(font);
+ * ----------------------------
+ * Changes the font used to display the <code>GLabel</code> as specified by
+ * the string <code>font</code>, which has the following format:
+ *
+ *<pre>
+ * family-style-size
+ *</pre>
+ *
+ * where both <code>style</code> and <code>size</code> are optional.
+ * If any of these elements are missing or specified as an asterisk,
+ * the existing value is retained.
+ */
+
+ void setFont(std::string font);
+
+/*
+ * Method: getFont
+ * Usage: string font = label->getFont();
+ * --------------------------------------
+ * Returns the current font for the <code>GLabel</code>.
+ */
+
+ std::string getFont() const;
+
+/*
+ * Method: setLabel
+ * Usage: label->setLabel(str);
+ * ----------------------------
+ * Changes the string stored within the <code>GLabel</code> object, so that
+ * a new text string appears on the display.
+ */
+
+ void setLabel(std::string str);
+
+/*
+ * Method: getLabel
+ * Usage: string str = label->getLabel();
+ * --------------------------------------
+ * Returns the string displayed by this object.
+ */
+
+ std::string getLabel() const;
+
+/*
+ * Method: getFontAscent
+ * Usage: double ascent = label->getFontAscent();
+ * ----------------------------------------------
+ * Returns the maximum distance strings in this font extend above
+ * the baseline.
+ */
+
+ double getFontAscent() const;
+
+/*
+ * Method: getFontDescent
+ * Usage: double descent = label->getFontDescent();
+ * ------------------------------------------------
+ * Returns the maximum distance strings in this font descend below
+ * the baseline.
+ */
+
+ double getFontDescent() const;
+
+/* Prototypes for the virtual methods */
+
+ virtual GRectangle getBounds() const;
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+private:
+
+/* Instance variables */
+
+ std::string str; /* The string displayed by the label */
+ std::string font; /* The font string of the label */
+ double width; /* Width of the bounding box */
+ double height; /* Height of the bounding box */
+ double ascent; /* Font ascent */
+ double descent; /* Font descent */
+
+ void createGLabel(const std::string & str);
+
+};
+
+/*
+ * Class: GLine
+ * ------------
+ * This graphical object subclass represents a line segment. For
+ * example, the following code adds lines that mark the diagonals
+ * of the graphics window:
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * cout << "This program draws the diagonals on the window." << endl;
+ * gw.add(new GLine(0, 0, gw.getWidth(), gw.getHeight()));
+ * gw.add(new GLine(0, gw.getHeight(), gw.getWidth(), 0));
+ * return 0;
+ * }
+ *</pre>
+ */
+
+class GLine : public GObject {
+
+public:
+
+/*
+ * Constructor: GLine
+ * Usage: GLine *gline = new GLine(x0, y0, x1, y1);
+ * ------------------------------------------------
+ * Constructs a line segment from its endpoints. The point
+ * (<code>x0</code>,&nbsp;<code>y0</code>) defines the start of the
+ * line and the point (<code>x1</code>,&nbsp;<code>y1</code>) defines
+ * the end.
+ */
+
+ GLine(double x0, double y0, double x1, double y1);
+
+/*
+ * Method: setStartPoint
+ * Usage: line->setStartPoint(x, y);
+ * ---------------------------------
+ * Sets the initial point in the line to (<code>x</code>,&nbsp;<code>y</code>),
+ * leaving the end point unchanged. This method is therefore different from
+ * <code>setLocation</code>, which moves both components of the line segment.
+ */
+
+ void setStartPoint(double x, double y);
+
+/*
+ * Method: getStartPoint
+ * Usage: GPoint pt = line->getStartPoint();
+ * -----------------------------------------
+ * Returns the point at which the line starts.
+ */
+
+ GPoint getStartPoint() const;
+
+/*
+ * Method: setEndPoint
+ * Usage: line->setEndPoint(x, y);
+ * -------------------------------
+ * Sets the end point in the line to (<code>x</code>,&nbsp;<code>y</code>),
+ * leaving the start point unchanged. This method is therefore different from
+ * <code>setLocation</code>, which moves both components of the line segment.
+ */
+
+ void setEndPoint(double x, double y);
+
+/*
+ * Method: getEndPoint
+ * Usage: GPoint pt = line->getEndPoint();
+ * ---------------------------------------
+ * Returns the point at which the line ends.
+ */
+
+ GPoint getEndPoint() const;
+
+/* Prototypes for the virtual methods */
+
+ virtual GRectangle getBounds() const;
+ virtual bool contains(double x, double y) const;
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+protected:
+
+/* Instance variables */
+
+ double dx; /* The x displacement of the line */
+ double dy; /* The y displacement of the line */
+
+};
+
+/*
+ * Class: GPolygon
+ * ---------------
+ * This graphical object subclass represents a polygon bounded by
+ * line segments. The <code>GPolygon</code> constructor creates an
+ * empty polygon. To complete the figure, you need to add vertices
+ * to the polygon using the methods
+ * <a href="#Method:addVertex"><code>addVertex</code></a>,
+ * <a href="#Method:addEdge"><code>addEdge</code></a>,
+ * and <a href="#Method:addPolarEdge"><code>addPolarEdge</code></a>.
+ * As an example, the following code adds a filled red octagon to
+ * the center of the window:
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * cout << "This program draws a red octagon." << endl;
+ * double edge = 75;
+ * GPolygon *stopSign = new GPolygon();
+ * stopSign->addVertex(-edge / 2, edge / 2 + edge / sqrt(2.0));
+ * for (int i = 0; i < 8; i++) {
+ * stopSign->addPolarEdge(edge, 45 * i);
+ * }
+ * stopSign->setFilled(true);
+ * stopSign->setColor("RED");
+ * gw.add(stopSign, gw.getWidth() / 2, gw.getHeight() / 2);
+ * return 0;
+ * }
+ *</pre>
+ * <include src="pictures/GObjectDiagrams/StopSign.html">
+ */
+
+class GPolygon : public GObject {
+
+public:
+
+/*
+ * Constructor: GPolygon
+ * Usage: GPolygon *poly = new GPolygon();
+ * ---------------------------------------
+ * Constructs a new empty polygon at the origin.
+ */
+
+ GPolygon();
+
+/*
+ * Method: addVertex
+ * Usage: poly->addVertex(x, y);
+ * -----------------------------
+ * Adds a vertex at (<code>x</code>, <code>y</code>) relative to the polygon
+ * origin.
+ */
+
+ void addVertex(double x, double y);
+
+/*
+ * Method: addEdge
+ * Usage: poly->addEdge(dx, dy);
+ * -----------------------------
+ * Adds an edge to the polygon whose components are given by the displacements
+ * <code>dx</code> and <code>dy</code> from the last vertex.
+ */
+
+ void addEdge(double dx, double dy);
+
+/*
+ * Method: addPolarEdge
+ * Usage: poly->addPolarEdge(r, theta);
+ * ------------------------------------
+ * Adds an edge to the polygon specified in polar coordinates. The length
+ * of the edge is given by <code>r</code>, and the edge extends in
+ * direction <code>theta</code>, measured in degrees counterclockwise
+ * from the +x axis.
+ */
+
+ void addPolarEdge(double r, double theta);
+
+/*
+ * Method: getVertices
+ * Usage: Vector<GPoint> vec = poly->getVertices();
+ * ------------------------------------------------
+ * Returns a vector of the points in the polygon.
+ */
+
+ Vector<GPoint> getVertices() const;
+
+/*
+ * Method: setFilled
+ * Usage: poly->setFilled(flag);
+ * -----------------------------
+ * Sets the fill status for the polygon, where <code>false</code> is
+ * outlined and <code>true</code> is filled.
+ */
+
+ void setFilled(bool flag);
+
+/*
+ * Method: isFilled
+ * Usage: if (poly->isFilled()) ...
+ * --------------------------------
+ * Returns <code>true</code> if the polygon is filled.
+ */
+
+ bool isFilled() const;
+
+/*
+ * Method: setFillColor
+ * Usage: poly->setFillColor(color);
+ * ---------------------------------
+ * Sets the color used to display the filled region of this polygon.
+ */
+
+ void setFillColor(std::string color);
+ void setFillColor(int rgb);
+
+/*
+ * Method: getFillColor
+ * Usage: string color = poly->getFillColor();
+ * -------------------------------------------
+ * Returns the color used to display the filled region of this polygon. If
+ * none has been set, <code>getFillColor</code> returns the empty string.
+ */
+
+ std::string getFillColor() const;
+
+/* Prototypes for the virtual methods */
+
+ virtual GRectangle getBounds() const;
+ virtual bool contains(double x, double y) const;
+ virtual std::string getType() const;
+ virtual std::string toString() const;
+
+private:
+
+/* Instance variables */
+
+ Vector<GPoint> vertices; /* The vertices of the polygon */
+ double cx; /* The most recent x coordinate */
+ double cy; /* The most recent y coordinate */
+ std::string fillColor; /* The color of the interior */
+ bool fillFlag; /* Indicates if object is filled */
+
+};
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/graph.h b/labb8/lib/StanfordCPPLib/graph.h
new file mode 100755
index 0000000..30fae8f
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/graph.h
@@ -0,0 +1,836 @@
+/*
+ * File: graph.h
+ * -------------
+ * This file exports a parameterized <code>Graph</code> class used
+ * to represent <b><i>graphs,</i></b> which consist of a set of
+ * <b><i>nodes</i></b> and a set of <b><i>arcs</i></b>.
+ */
+
+#ifndef _graph_h
+#define _graph_h
+
+#include <string>
+#include "map.h"
+#include "set.h"
+#include "tokenscanner.h"
+
+/*
+ * Class: Graph<NodeType,ArcType>
+ * ------------------------------
+ * This class represents a graph with the specified node and arc types.
+ * The <code>NodeType</code> and <code>ArcType</code> parameters indicate
+ * the structure type or class used for nodes and arcs, respectively.
+ * These types can contain any fields or methods required by the client,
+ * but must contain the following fields required by the <code>Graph</code>
+ * package itself:
+ *
+ * <p>The <code>NodeType</code> definition must include:
+ * <ul>
+ * <li>A <code>string</code> field called <code>name</code>
+ * <li>A <code>Set&lt;ArcType *&gt;</code> field called <code>arcs</code>
+ * </ul>
+ *
+ * <p>The <code>ArcType</code> definition must include:
+ * <ul>
+ * <li>A <code>NodeType *</code> field called <code>start</code>
+ * <li>A <code>NodeType *</code> field called <code>finish</code>
+ * </ul>
+ */
+
+template <typename NodeType,typename ArcType>
+class Graph {
+
+public:
+
+/*
+ * Constructor: Graph
+ * Usage: Graph<NodeType,ArcType> g;
+ * ---------------------------------
+ * Creates an empty <code>Graph</code> object.
+ */
+
+ Graph();
+
+/*
+ * Destructor: ~Graph
+ * ------------------
+ * Frees the internal storage allocated to represent the graph.
+ */
+
+ virtual ~Graph();
+
+/*
+ * Method: size
+ * Usage: int size = g.size();
+ * ---------------------------
+ * Returns the number of nodes in the graph.
+ */
+
+ int size() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (g.isEmpty()) ...
+ * ---------------------------
+ * Returns <code>true</code> if the graph is empty.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: clear
+ * Usage: g.clear();
+ * -----------------
+ * Reinitializes the graph to be empty, freeing any heap storage.
+ */
+
+ void clear();
+
+/*
+ * Method: addNode
+ * Usage: NodeType *node = g.addNode(name);
+ * NodeType *node = g.addNode(node);
+ * ----------------------------------------
+ * Adds a node to the graph. The first version of this method
+ * creates a new node of the appropriate type and initializes its
+ * fields; the second assumes that the client has already created
+ * the node and simply adds it to the graph. Both versions of this
+ * method return a pointer to the node.
+ */
+
+ NodeType *addNode(std::string name);
+ NodeType *addNode(NodeType *node);
+
+/*
+ * Method: removeNode
+ * Usage: g.removeNode(name);
+ * g.removeNode(node);
+ * --------------------------
+ * Removes a node from the graph, where the node can be specified
+ * either by its name or as a pointer value. Removing a node also
+ * removes all arcs that contain that node.
+ */
+
+ void removeNode(std::string name);
+ void removeNode(NodeType *node);
+
+/*
+ * Method: getNode
+ * Usage: NodeType *node = g.getNode(name);
+ * ----------------------------------------
+ * Looks up a node in the name table attached to the graph and
+ * returns a pointer to that node. If no node with the specified
+ * name exists, <code>getNode</code> returns <code>NULL</code>.
+ */
+
+ NodeType *getNode(std::string name) const;
+
+/*
+ * Method: addArc
+ * Usage: g.addArc(s1, s2);
+ * g.addArc(n1, n2);
+ * g.addArc(arc);
+ * ---------------------
+ * Adds an arc to the graph. The endpoints of the arc can be specified
+ * either as strings indicating the names of the nodes or as pointers
+ * to the node structures. Alternatively, the client can create the arc
+ * structure explicitly and pass that pointer to the <code>addArc</code>
+ * method. All three of these versions return a pointer to the arc in
+ * case the client needs to capture this value.
+ */
+
+ ArcType *addArc(std::string s1, std::string s2);
+ ArcType *addArc(NodeType *n1, NodeType *n2);
+ ArcType *addArc(ArcType *arc);
+
+/*
+ * Method: removeArc
+ * Usage: g.removeArc(s1, s2);
+ * g.removeArc(n1, n2);
+ * g.removeArc(arc);
+ * ------------------------
+ * Removes an arc from the graph, where the arc can be specified in any
+ * of three ways: by the names of its endpoints, by the node pointers
+ * at its endpoints, or as an arc pointer. If more than one arc
+ * connects the specified endpoints, all of them are removed.
+ */
+
+ void removeArc(std::string s1, std::string s2);
+ void removeArc(NodeType *n1, NodeType *n2);
+ void removeArc(ArcType *arc);
+
+/*
+ * Method: isConnected
+ * Usage: if (g.isConnected(n1, n2)) ...
+ * if (g.isConnected(s1, s2)) ...
+ * -------------------------------------
+ * Returns <code>true</code> if the graph contains an arc from
+ * <code>n1</code> to <code>n2</code>. As in the <code>addArc</code>
+ * method, nodes can be specified either as node pointers or by name.
+ */
+
+ bool isConnected(NodeType *n1, NodeType *n2) const;
+ bool isConnected(std::string s1, std::string s2) const;
+
+/*
+ * Method: getNodeSet
+ * Usage: foreach (NodeType *node in g.getNodeSet()) ...
+ * -----------------------------------------------------
+ * Returns the set of all nodes in the graph.
+ */
+
+ const Set<NodeType *> & getNodeSet() const;
+
+/*
+ * Method: getArcSet
+ * Usage: foreach (ArcType *arc in g.getArcSet()) ...
+ * foreach (ArcType *arc in g.getArcSet(node)) ...
+ * foreach (ArcType *arc in g.getArcSet(name)) ...
+ * ------------------------------------------------------
+ * Returns the set of all arcs in the graph or, in the second and
+ * third forms, the arcs that start at the specified node, which
+ * can be indicated either as a pointer or by name.
+ */
+
+ const Set<ArcType *> & getArcSet() const;
+ const Set<ArcType *> & getArcSet(NodeType *node) const;
+ const Set<ArcType *> & getArcSet(std::string name) const;
+
+/*
+ * Method: getNeighbors
+ * Usage: foreach (NodeType *node in g.getNeighbors(node)) ...
+ * foreach (NodeType *node in g.getNeighbors(name)) ...
+ * -----------------------------------------------------------
+ * Returns the set of nodes that are neighbors of the specified
+ * node, which can be indicated either as a pointer or by name.
+ */
+
+ const Set<NodeType *> getNeighbors(NodeType *node) const;
+ const Set<NodeType *> getNeighbors(std::string node) const;
+
+/*
+ * Method: toString
+ * Usage: string str = g.toString();
+ * ---------------------------------
+ * Converts the graph to a printable string representation.
+ */
+
+ std::string toString();
+
+/*
+ * Friend method: writeNodeData
+ * Usage: writeNodeData(os, NodeType *node);
+ * -----------------------------------------
+ * Writes the data for the node to the output stream. The default
+ * implementation of this method is empty. Clients that want to store
+ * other fields from the node must override this method so that it
+ * writes that data in a form that scanNodeData can read.
+ */
+
+ virtual void writeNodeData(std::ostream &, NodeType *) const {
+ /* Empty */
+ }
+
+/*
+ * Friend method: writeArcData
+ * Usage: writeArcData(os, ArcType *arc);
+ * --------------------------------------
+ * Writes the data for the arc to the output stream. The default
+ * implementation of this method is empty. Clients that want to store
+ * other fields from the arc must override this method so that it writes
+ * that data in a form that scanArcData can read.
+ */
+
+ virtual void writeArcData(std::ostream &, ArcType *) const {
+ /* Empty */
+ }
+
+/*
+ * Friend method: scanGraphEntry
+ * Usage: while (g.scanGraphEntry(scanner)) { }
+ * --------------------------------------------
+ * This method reads one "entry" for the graph, which is either a node
+ * description or an arc description. The <code>scanGraphEntry</code>
+ * method returns <code>true</code> if it reads an entry, and
+ * <code>false</code> at the end of file or at text that cannot be
+ * recognized as a graph entry.
+ *
+ * <p>Node entries consist of the name of a node (which may be quoted
+ * if it contains special characters), optionally followed by data for
+ * the node. Arc descriptions have one of the following forms:
+ *
+ *<pre>
+ * n1 -> n2
+ * n1 - n2
+ *</pre>
+ *
+ * either of which can be followed by data for the arc. The first form
+ * creates a single directed arc; the second creates two arcs, one in
+ * each direction.
+ *
+ * <p>Clients who want to read node or arc data must override the empty
+ * versions of <code>scanNodeData</code> and <code>scanArcData</code>
+ * included in this interface.
+ */
+
+ virtual bool scanGraphEntry(TokenScanner & scanner);
+
+/*
+ * Friend method: scanNodeData
+ * Usage: scanNodeData(scanner, NodeType *node);
+ * ---------------------------------------------
+ * Reads the data for the specified node from the scanner. The default
+ * implementation of this method is empty. Clients that want to initialize
+ * other fields in the node from the token stream must override this method.
+ */
+
+ virtual void scanNodeData(TokenScanner &, NodeType *) {
+ /* Empty */
+ }
+
+/*
+ * Friend method: scanArcData
+ * Usage: scanArcData(scanner, ArcType *forward, ArcType *backward);
+ * -----------------------------------------------------------------
+ * Reads the data for an arc from the scanner. The <code>forward</code>
+ * argument points to the arc in the forward direction. If the arc is
+ * undirected, <code>backward</code> points to the reverse arc; for
+ * directed arcs, the <code>backward</code> pointer is <code>NULL</code>.
+ * The default implementation of this method is empty. Clients that want
+ * to initialize other fields in the arc must override this method so
+ * that it initializes one or both arc, as appropriate.
+ */
+
+ virtual void scanArcData(TokenScanner &, ArcType *, ArcType *) {
+ /* Empty */
+ }
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+/*
+ * Private class: GraphComparator
+ * ------------------------------
+ * This template class establishes the ordering for nodes and arcs.
+ * Nodes are processed in alphabetical order by node name; arcs are
+ * compared in much the same way, looking first at the start node and
+ * then continuing on to look at the finish node if the start nodes
+ * match. These functions, however, indicate equality only if the
+ * arguments are identical, in the sense that they are at the same
+ * address. If two distinct arcs, for example, connect the same pair
+ * of nodes (which is perfectly legal in the graph abstraction and can
+ * be used, for example, to represent multiple modes of travel between
+ * two nodes), those arcs are not the same.
+ */
+
+ class GraphComparator {
+ public:
+
+ bool operator()(NodeType *n1, NodeType *n2) {
+ return compare(n1, n2) < 0;
+ }
+
+ bool operator()(ArcType *a1, ArcType *a2) {
+ return compare(a1, a2) < 0;
+ }
+
+ };
+
+private:
+
+/* Instance variables */
+
+ Set<NodeType *> nodes; /* The set of nodes in the graph */
+ Set<ArcType *> arcs; /* The set of arcs in the graph */
+ Map<std::string, NodeType *> nodeMap; /* A map from names to nodes */
+ GraphComparator comparator; /* The comparator for this graph */
+
+/*
+ * Functions: operator=, copy constructor
+ * --------------------------------------
+ * These functions are part of the public interface of the class but are
+ * defined here to avoid adding confusion to the Graph class.
+ */
+
+public:
+
+ Graph & operator=(const Graph & src);
+ Graph(const Graph & src);
+
+ static int compare(NodeType *n1, NodeType *n2) {
+ if (n1 == n2) return 0;
+ if (n1->name < n2->name) return -1;
+ if (n1->name > n2->name) return +1;
+ return (n1 < n2) ? -1 : +1;
+ }
+
+ static int compare(ArcType *a1, ArcType *a2) {
+ if (a1 == a2) return 0;
+ NodeType *n1 = a1->start;
+ NodeType *n2 = a2->start;
+ if (n1 != n2) return compare(n1, n2);
+ n1 = a1->finish;
+ n2 = a2->finish;
+ if (n1 != n2) return compare(n1, n2);
+ return (a1 < a2) ? -1 : +1;
+ }
+
+private:
+
+ void deepCopy(const Graph & src);
+ NodeType *getExistingNode(std::string name) const;
+ NodeType *scanNode(TokenScanner & scanner);
+
+};
+
+extern void error(std::string msg);
+
+/*
+ * Implementation notes: Graph constructor
+ * ---------------------------------------
+ * Even though the body of the Graph constructor is empty, important
+ * work is done by the initializers, which ensure that the nodes and
+ * arcs set are given the correct comparison functions.
+ */
+
+template <typename NodeType,typename ArcType>
+Graph<NodeType,ArcType>::Graph() {
+ comparator = GraphComparator();
+ nodes = Set<NodeType *>(comparator);
+ arcs = Set<ArcType *>(comparator);
+}
+
+/*
+ * Implementation notes: Graph destructor
+ * --------------------------------------
+ * The destructor must free all heap storage used by this graph to
+ * represent the nodes and arcs. The clear metho must also reclaim
+ * this memory, which means that the destructor can simply call
+ * clear to do the work.
+ */
+
+template <typename NodeType,typename ArcType>
+Graph<NodeType,ArcType>::~Graph() {
+ clear();
+}
+
+/*
+ * Implementation notes: size, isEmpty
+ * -----------------------------------
+ * These methods are defined in terms of the node set, so the implementation
+ * simply forwards the request there. Note that it is impossible for a
+ * graph to have arcs if it has no nodes.
+ */
+
+template <typename NodeType,typename ArcType>
+int Graph<NodeType,ArcType>::size() const {
+ return nodes.size();
+}
+
+template <typename NodeType,typename ArcType>
+bool Graph<NodeType,ArcType>::isEmpty() const {
+ return nodes.isEmpty();
+}
+
+/*
+ * Implementation notes: clear
+ * ---------------------------
+ * The implementation of clear first frees the nodes and arcs in
+ * their respective sets and then uses the Set class clear method
+ * to ensure that these sets are empty.
+ */
+
+template <typename NodeType,typename ArcType>
+void Graph<NodeType,ArcType>::clear() {
+ foreach (NodeType *node in nodes) {
+ delete node;
+ }
+ foreach (ArcType *arc in arcs) {
+ delete arc;
+ }
+ arcs.clear();
+ nodes.clear();
+ nodeMap.clear();
+}
+
+/*
+ * Implementation notes: addNode
+ * -----------------------------
+ * The addNode method appears in two forms: one that creates a node
+ * from its name and one that assumes that the client has created
+ * the new node. In each case, the implementation must add the node
+ * the set of nodes for the graph and add the name-to-node association
+ * to the node map.
+ */
+
+template <typename NodeType,typename ArcType>
+NodeType *Graph<NodeType,ArcType>::addNode(std::string name) {
+ NodeType *node = new NodeType();
+ node->arcs = Set<ArcType *>(comparator);
+ node->name = name;
+ return addNode(node);
+}
+
+template <typename NodeType,typename ArcType>
+NodeType *Graph<NodeType,ArcType>::addNode(NodeType *node) {
+ if (nodeMap.containsKey(node->name)) {
+ error("addNode: node " + node->name + " already exists");
+ }
+ nodes.add(node);
+ nodeMap[node->name] = node;
+ return node;
+}
+
+/*
+ * Implementation notes: removeNode
+ * --------------------------------
+ * The removeNode method must remove the specified node but must
+ * also remove any arcs in the graph containing the node. To avoid
+ * changing the node set during iteration, this implementation creates
+ * a vector of arcs that require deletion.
+ */
+
+template <typename NodeType,typename ArcType>
+void Graph<NodeType,ArcType>::removeNode(std::string name) {
+ removeNode(getExistingNode(name));
+}
+
+template <typename NodeType,typename ArcType>
+void Graph<NodeType,ArcType>::removeNode(NodeType *node) {
+ Vector<ArcType *> toRemove;
+ foreach (ArcType *arc in arcs) {
+ if (arc->start == node || arc->finish == node) {
+ toRemove.add(arc);
+ }
+ }
+ foreach (ArcType *arc in toRemove) {
+ removeArc(arc);
+ }
+ nodes.remove(node);
+}
+
+/*
+ * Implementation notes: getNode, getExistingNode
+ * ----------------------------------------------
+ * The getNode method simply looks up the name in the map, which correctly
+ * returns NULL if the name is not found. Other methods in the
+ * implementation call the private method getExistingNode instead,
+ * which checks for a NULL value and signals an error.
+ */
+
+template <typename NodeType,typename ArcType>
+NodeType *Graph<NodeType,ArcType>::getNode(std::string name) const {
+ return nodeMap.get(name);
+}
+
+template <typename NodeType,typename ArcType>
+NodeType *Graph<NodeType,ArcType>::getExistingNode(std::string name) const {
+ NodeType *node = nodeMap.get(name);
+ if (node == NULL) error("Graph class: No node named " + name);
+ return node;
+}
+
+/*
+ * Implementation notes: addArc
+ * ----------------------------
+ * The addArc method appears in three forms, as described in the
+ * interface. The code for each form of the method, however, is
+ * quite straightforward.
+ */
+
+template <typename NodeType,typename ArcType>
+ArcType *Graph<NodeType,ArcType>::addArc(std::string s1, std::string s2) {
+ return addArc(getExistingNode(s1), getExistingNode(s2));
+}
+
+template <typename NodeType,typename ArcType>
+ArcType *Graph<NodeType,ArcType>::addArc(NodeType *n1, NodeType *n2) {
+ ArcType *arc = new ArcType();
+ arc->start = n1;
+ arc->finish = n2;
+ return addArc(arc);
+}
+
+template <typename NodeType,typename ArcType>
+ArcType *Graph<NodeType,ArcType>::addArc(ArcType *arc) {
+ arc->start->arcs.add(arc);
+ arcs.add(arc);
+ return arc;
+}
+
+/*
+ * Implementation notes: removeArc
+ * -------------------------------
+ * These methods remove arcs from the graph, which is ordinarily simply
+ * a matter of removing the arc from two sets: the set of arcs in the
+ * graph as a whole and the set of arcs in the starting node. The
+ * methods that remove an arc specified by its endpoints, however,
+ * must take account of the fact that there might be more than one
+ * such arc and delete all of them.
+ */
+
+template <typename NodeType,typename ArcType>
+void Graph<NodeType,ArcType>::removeArc(std::string s1, std::string s2) {
+ removeArc(getExistingNode(s1), getExistingNode(s2));
+}
+
+template <typename NodeType,typename ArcType>
+void Graph<NodeType,ArcType>::removeArc(NodeType *n1, NodeType *n2) {
+ Vector<ArcType *> toRemove;
+ foreach (ArcType *arc in arcs) {
+ if (arc->start == n1 && arc->finish == n2) {
+ toRemove.add(arc);
+ }
+ }
+ foreach (ArcType *arc in toRemove) {
+ removeArc(arc);
+ }
+}
+
+template <typename NodeType,typename ArcType>
+void Graph<NodeType,ArcType>::removeArc(ArcType *arc) {
+ arc->start->arcs.remove(arc);
+ arcs.remove(arc);
+}
+
+/*
+ * Implementation notes: isConnected
+ * ---------------------------------
+ * Node n1 is connected to n2 if any of the arcs leaving n1 finish at n2.
+ * The two versions of this method allow nodes to be specified either as
+ * node pointers or by name.
+ */
+
+template <typename NodeType,typename ArcType>
+bool Graph<NodeType,ArcType>::isConnected(NodeType *n1, NodeType *n2) const {
+ foreach (ArcType *arc in n1->arcs) {
+ if (arc->finish == n2) return true;
+ }
+ return false;
+}
+
+template <typename NodeType,typename ArcType>
+bool Graph<NodeType,ArcType>::isConnected(std::string s1,
+ std::string s2) const {
+ return isConnected(getExistingNode(s1), getExistingNode(s2));
+}
+
+/*
+ * Implementation notes: getNodeSet, getArcSet
+ * -------------------------------------------
+ * These methods simply return the set requested by the client. The
+ * sets are returned by reference for efficiency, because doing so
+ * eliminates the need to copy the set.
+ */
+
+template <typename NodeType,typename ArcType>
+const Set<NodeType *> & Graph<NodeType,ArcType>::getNodeSet() const {
+ return nodes;
+}
+
+template <typename NodeType,typename ArcType>
+const Set<ArcType *> & Graph<NodeType,ArcType>::getArcSet() const {
+ return arcs;
+}
+
+template <typename NodeType,typename ArcType>
+const Set<ArcType *> &
+ Graph<NodeType,ArcType>::getArcSet(NodeType *node) const {
+ return node->arcs;
+}
+
+template <typename NodeType,typename ArcType>
+const Set<ArcType *> &
+ Graph<NodeType,ArcType>::getArcSet(std::string name) const {
+ return getArcSet(getExistingNode(name));
+}
+
+/*
+ * Implementation notes: getNeighbors
+ * ----------------------------------
+ * This implementation recomputes the set each time, which is reasonably
+ * efficient if the degree of the node is small.
+ */
+
+template <typename NodeType,typename ArcType>
+const Set<NodeType *>
+ Graph<NodeType,ArcType>::getNeighbors(NodeType *node) const {
+ Set<NodeType *> nodes = Set<NodeType *>(comparator);
+ foreach (ArcType *arc in node->arcs) {
+ nodes.add(arc->finish);
+ }
+ return nodes;
+}
+
+template <typename NodeType,typename ArcType>
+const Set<NodeType *>
+ Graph<NodeType,ArcType>::getNeighbors(std::string name) const {
+ return getNeighbors(getExistingNode(name));
+}
+
+/*
+ * Implementation notes: operator=, copy constructor
+ * -------------------------------------------------
+ * These methods ensure that copying a graph creates an entirely new
+ * parallel structure of nodes and arcs.
+ */
+
+template <typename NodeType,typename ArcType>
+Graph<NodeType,ArcType>
+ & Graph<NodeType,ArcType>::operator=(const Graph & src) {
+ if (this != &src) {
+ clear();
+ deepCopy(src);
+ }
+ return *this;
+}
+
+template <typename NodeType,typename ArcType>
+Graph<NodeType,ArcType>::Graph(const Graph & src) {
+ nodes = Set<NodeType *>(comparator);
+ arcs = Set<ArcType *>(comparator);
+ deepCopy(src);
+}
+
+/*
+ * Private method: deepCopy
+ * ------------------------
+ * Common code factored out of the copy constructor and operator= to
+ * copy the contents from the other graph.
+ */
+
+template <typename NodeType,typename ArcType>
+void Graph<NodeType,ArcType>::deepCopy(const Graph & src) {
+ foreach (NodeType *oldNode in src.nodes) {
+ NodeType *newNode = new NodeType();
+ *newNode = *oldNode;
+ newNode->arcs.clear();
+ addNode(newNode);
+ }
+ foreach (ArcType *oldArc in src.arcs) {
+ ArcType *newArc = new ArcType();
+ *newArc = *oldArc;
+ newArc->start = getExistingNode(oldArc->start->name);
+ newArc->finish = getExistingNode(oldArc->finish->name);
+ addArc(newArc);
+ }
+}
+
+template <typename NodeType,typename ArcType>
+std::string Graph<NodeType,ArcType>::toString() {
+ ostringstream os;
+ os << *this;
+ return os.str();
+}
+
+/*
+ * Implementation notes: scanGraphEntry
+ * ------------------------------------
+ * The scanGraphEntry and its helper methods take a scanner that is
+ * initialized to the input stream and has the options ignoreWhitespace,
+ * scanStrings, and scanNumbers set.
+ */
+
+template <typename NodeType,typename ArcType>
+bool Graph<NodeType,ArcType>::scanGraphEntry(TokenScanner & scanner) {
+ NodeType *n1 = scanNode(scanner);
+ if (n1 == NULL) return false;
+ std::string op = scanner.nextToken();
+ if (op != "-" && op != "->") {
+ scanner.saveToken(op);
+ return true;
+ }
+ NodeType *n2 = scanNode(scanner);
+ if (n2 == NULL) error("scanGraphEntry: Missing node after " + op);
+ ArcType *forward = new ArcType();
+ forward->start = n1;
+ forward->finish = n2;
+ addArc(forward);
+ ArcType *backward = NULL;
+ if (op == "-") {
+ backward = new ArcType();
+ backward->start = n2;
+ backward->finish = n1;
+ addArc(backward);
+ }
+ scanArcData(scanner, forward, backward);
+ return true;
+}
+
+template <typename NodeType,typename ArcType>
+NodeType *Graph<NodeType,ArcType>::scanNode(TokenScanner & scanner) {
+ std::string token = scanner.nextToken();
+ switch (scanner.getTokenType(token)) {
+ case WORD: break;
+ case STRING: token = scanner.getStringValue(token); break;
+ default: scanner.saveToken(token); return NULL;
+ }
+ NodeType *node = getNode(token);
+ if (node == NULL) {
+ node = new NodeType();
+ node->name = token;
+ scanNodeData(scanner, node);
+ addNode(node);
+ }
+ return node;
+}
+
+/*
+ * Implementation notes: << and >>
+ * -------------------------------
+ * The insertion and extraction operators for graphs are more complicated
+ * than for the standard collection types because the nodes and arcs can
+ * contain client-specific data. To ensure that this information is
+ * correctly written and read by these operators, clients must override
+ * the methods writeNodeData, writeArcData, scanNodeData, and scanArcData.
+ */
+
+template <typename NodeType,typename ArcType>
+std::ostream & operator<<(std::ostream & os,
+ const Graph<NodeType,ArcType> & g) {
+ os << "{";
+ bool started = false;
+ foreach (NodeType *node in g.getNodeSet()) {
+ if (started) os << ", ";
+ writeGenericValue(os, node->name, false);
+ g.writeNodeData(os, node);
+ started = true;
+ }
+ foreach (ArcType *arc in g.getArcSet()) {
+ os << ", ";
+ writeGenericValue(os, arc->start->name, false);
+ os << " -> ";
+ writeGenericValue(os, arc->finish->name, false);
+ g.writeArcData(os, arc);
+ }
+ return os << "}";
+}
+
+template <typename NodeType,typename ArcType>
+std::istream & operator>>(std::istream & is, Graph<NodeType,ArcType> & g) {
+ TokenScanner scanner(is);
+ scanner.ignoreWhitespace();
+ scanner.scanNumbers();
+ scanner.scanStrings();
+ scanner.addOperator("->");
+ std::string token = scanner.nextToken();
+ if (token != "{") error("operator >>: Missing {");
+ g.clear();
+ while (g.scanGraphEntry(scanner)) {
+ token = scanner.nextToken();
+ if (token == "}") {
+ scanner.saveToken(token);
+ } else if (token != ",") {
+ error("operator >>: Unexpected token " + token);
+ }
+ }
+ token = scanner.nextToken();
+ if (token != "}") error("operator >>: Missing }");
+ return is;
+}
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/grid.h b/labb8/lib/StanfordCPPLib/grid.h
new file mode 100755
index 0000000..0a23b46
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/grid.h
@@ -0,0 +1,516 @@
+/*
+ * File: grid.h
+ * ------------
+ * This file exports the <code>Grid</code> class, which offers a
+ * convenient abstraction for representing a two-dimensional array.
+ */
+
+#ifndef _grid_h
+#define _grid_h
+
+#include "foreach.h"
+#include "strlib.h"
+#include "vector.h"
+
+/*
+ * Class: Grid<ValueType>
+ * ----------------------
+ * This class stores an indexed, two-dimensional array. The following code,
+ * for example, creates an identity matrix of size <code>n</code>, in which
+ * the elements are 1.0 along the main diagonal and 0.0 everywhere else:
+ *
+ *<pre>
+ * Grid&lt;double&gt; createIdentityMatrix(int n) {
+ * Grid&lt;double&gt; matrix(n, n);
+ * for (int i = 0; i &lt; n; i++) {
+ * matrix[i][i] = 1.0;
+ * }
+ * return matrix;
+ * }
+ *</pre>
+ */
+
+template <typename ValueType>
+class Grid {
+
+public:
+
+/* Forward reference */
+ class GridRow;
+
+/*
+ * Constructor: Grid
+ * Usage: Grid<ValueType> grid;
+ * Grid<ValueType> grid(nRows, nCols);
+ * ------------------------------------------
+ * Initializes a new grid. The second form of the constructor is
+ * more common and creates a grid with the specified number of rows
+ * and columns. Each element of the grid is initialized to the
+ * default value for the type. The default constructor creates an
+ * empty grid for which the client must call <code>resize</code> to
+ * set the dimensions.
+ */
+
+ Grid();
+ Grid(int nRows, int nCols);
+
+/*
+ * Destructor: ~Grid
+ * -----------------
+ * Frees any heap storage associated with this grid.
+ */
+
+ virtual ~Grid();
+
+/*
+ * Method: numRows
+ * Usage: int nRows = grid.numRows();
+ * ----------------------------------
+ * Returns the number of rows in the grid.
+ */
+
+ int numRows() const;
+
+/*
+ * Method: numCols
+ * Usage: int nCols = grid.numCols();
+ * ----------------------------------
+ * Returns the number of columns in the grid.
+ */
+
+ int numCols() const;
+
+/*
+ * Method: resize
+ * Usage: grid.resize(nRows, nCols);
+ * ---------------------------------
+ * Reinitializes the grid to have the specified number of rows
+ * and columns. Any previous grid contents are discarded.
+ */
+
+ void resize(int nRows, int nCols);
+
+/*
+ * Method: inBounds
+ * Usage: if (grid.inBounds(row, col)) ...
+ * ---------------------------------------
+ * Returns <code>true</code> if the specified row and column position
+ * is inside the bounds of the grid.
+ */
+
+ bool inBounds(int row, int col) const;
+
+/*
+ * Method: get
+ * Usage: ValueType value = grid.get(row, col);
+ * --------------------------------------------
+ * Returns the element at the specified <code>row</code>/<code>col</code>
+ * position in this grid. This method signals an error if the
+ * <code>row</code> and <code>col</code> arguments are outside
+ * the grid boundaries.
+ */
+
+ ValueType get(int row, int col);
+ const ValueType & get(int row, int col) const;
+
+/*
+ * Method: set
+ * Usage: grid.set(row, col, value);
+ * ---------------------------------
+ * Replaces the element at the specified <code>row</code>/<code>col</code>
+ * location in this grid with a new value. This method signals an error
+ * if the <code>row</code> and <code>col</code> arguments are outside
+ * the grid boundaries.
+ */
+
+ void set(int row, int col, ValueType value);
+
+/*
+ * Operator: []
+ * Usage: grid[row][col]
+ * ----------------------
+ * Overloads <code>[]</code> to select elements from this grid.
+ * This extension enables the use of traditional array notation to
+ * get or set individual elements. This method signals an error if
+ * the <code>row</code> and <code>col</code> arguments are outside
+ * the grid boundaries.
+ */
+
+ GridRow operator[](int row);
+ const GridRow operator[](int row) const;
+
+/*
+ * Method: toString
+ * Usage: string str = grid.toString();
+ * ------------------------------------
+ * Converts the grid to a printable string representation.
+ */
+
+ std::string toString();
+
+/*
+ * Method: mapAll
+ * Usage: grid.mapAll(fn);
+ * -----------------------
+ * Calls the specified function on each element of the grid. The
+ * elements are processed in <b><i>row-major order,</i></b> in which
+ * all the elements of row 0 are processed, followed by the elements
+ * in row 1, and so on.
+ */
+
+ void mapAll(void (*fn)(ValueType value)) const;
+ void mapAll(void (*fn)(const ValueType & value)) const;
+
+ template <typename FunctorType>
+ void mapAll(FunctorType fn) const;
+
+/*
+ * Additional Grid operations
+ * --------------------------
+ * In addition to the methods listed in this interface, the Grid
+ * class supports the following operations:
+ *
+ * - Stream I/O using the << and >> operators
+ * - Deep copying for the copy constructor and assignment operator
+ * - Iteration using the range-based for statement and STL iterators
+ *
+ * The iteration forms process the grid in row-major order.
+ */
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+/*
+ * Implementation notes: Grid data structure
+ * -----------------------------------------
+ * The Grid is internally managed as a dynamic array of elements.
+ * The array itself is one-dimensional, the logical separation into
+ * rows and columns is done by arithmetic computation. The layout
+ * is in row-major order, which is to say that the entire first row
+ * is laid out contiguously, followed by the entire second row,
+ * and so on.
+ */
+
+/* Instance variables */
+
+ ValueType *elements; /* A dynamic array of the elements */
+ int nRows; /* The number of rows in the grid */
+ int nCols; /* The number of columns in the grid */
+
+/* Private method prototypes */
+
+ void checkRange(int row, int col);
+
+/*
+ * Hidden features
+ * ---------------
+ * The remainder of this file consists of the code required to
+ * support deep copying and iteration. Including these methods
+ * in the public interface would make that interface more
+ * difficult to understand for the average client.
+ */
+
+/*
+ * Deep copying support
+ * --------------------
+ * This copy constructor and operator= are defined to make a
+ * deep copy, making it possible to pass/return grids by value
+ * and assign from one grid to another. The entire contents of
+ * the grid, including all elements, are copied. Each grid
+ * element is copied from the original grid to the copy using
+ * assignment (operator=). Making copies is generally avoided
+ * because of the expense and thus, grids are typically passed
+ * by reference, however, when a copy is needed, these operations
+ * are supported.
+ */
+
+ void deepCopy(const Grid & grid) {
+ int n = grid.nRows * grid.nCols;
+ elements = new ValueType[n];
+ for (int i = 0; i < n; i++) {
+ elements[i] = grid.elements[i];
+ }
+ nRows = grid.nRows;
+ nCols = grid.nCols;
+ }
+
+public:
+
+ Grid & operator=(const Grid & src) {
+ if (this != &src) {
+ delete[] elements;
+ deepCopy(src);
+ }
+ return *this;
+ }
+
+ Grid(const Grid & src) {
+ deepCopy(src);
+ }
+
+/*
+ * Iterator support
+ * ----------------
+ * The classes in the StanfordCPPLib collection implement input
+ * iterators so that they work symmetrically with respect to the
+ * corresponding STL classes.
+ */
+
+ class iterator : public std::iterator<std::input_iterator_tag, ValueType> {
+
+ public:
+
+ iterator(const Grid *gp, int index) {
+ this->gp = gp;
+ this->index = index;
+ }
+
+ iterator(const iterator & it) {
+ this->gp = it.gp;
+ this->index = it.index;
+ }
+
+ iterator & operator++() {
+ index++;
+ return *this;
+ }
+
+ iterator operator++(int) {
+ iterator copy(*this);
+ operator++();
+ return copy;
+ }
+
+ bool operator==(const iterator & rhs) {
+ return gp == rhs.gp && index == rhs.index;
+ }
+
+ bool operator!=(const iterator & rhs) {
+ return !(*this == rhs);
+ }
+
+ ValueType & operator*() {
+ return gp->elements[index];
+ }
+
+ ValueType *operator->() {
+ return &gp->elements[index];
+ }
+
+ private:
+ const Grid *gp;
+ int index;
+ };
+
+ iterator begin() const {
+ return iterator(this, 0);
+ }
+
+ iterator end() const {
+ return iterator(this, nRows * nCols);
+ }
+
+/*
+ * Private class: Grid<ValType>::GridRow
+ * -------------------------------------
+ * This section of the code defines a nested class within the Grid template
+ * that makes it possible to use traditional subscripting on Grid values.
+ */
+
+ class GridRow {
+ public:
+ GridRow() {
+ /* Empty */
+ }
+
+ ValueType & operator[](int col) {
+ extern void error(std::string msg);
+ if (!gp->inBounds(row, col)) {
+ error("Grid index values out of range");
+ }
+ return gp->elements[(row * gp->nCols) + col];
+ }
+
+ ValueType operator[](int col) const {
+ extern void error(std::string msg);
+ if (!gp->inBounds(row, col)) {
+ error("Grid index values out of range");
+ }
+ return gp->elements[(row * gp->nCols) + col];
+ }
+
+ private:
+ GridRow(Grid *gridRef, int index) {
+ gp = gridRef;
+ row = index;
+ }
+
+ Grid *gp;
+ int row;
+ friend class Grid;
+ };
+ friend class GridRow;
+
+};
+
+extern void error(std::string msg);
+
+template <typename ValueType>
+Grid<ValueType>::Grid() {
+ elements = NULL;
+ nRows = 0;
+ nCols = 0;
+}
+
+template <typename ValueType>
+Grid<ValueType>::Grid(int nRows, int nCols) {
+ elements = NULL;
+ resize(nRows, nCols);
+}
+
+template <typename ValueType>
+Grid<ValueType>::~Grid() {
+ if (elements != NULL) delete[] elements;
+}
+
+template <typename ValueType>
+int Grid<ValueType>::numRows() const {
+ return nRows;
+}
+
+template <typename ValueType>
+int Grid<ValueType>::numCols() const {
+ return nCols;
+}
+
+template <typename ValueType>
+void Grid<ValueType>::resize(int nRows, int nCols) {
+ if (nRows < 0 || nCols < 0) {
+ error("Attempt to resize grid to invalid size ("
+ + integerToString(nRows) + ", "
+ + integerToString(nCols) + ")");
+ }
+ if (elements != NULL) delete[] elements;
+ this->nRows = nRows;
+ this->nCols = nCols;
+ elements = new ValueType[nRows * nCols];
+ ValueType value = ValueType();
+ for (int i = 0; i < nRows * nCols; i++) {
+ elements[i] = value;
+ }
+}
+
+template <typename ValueType>
+bool Grid<ValueType>::inBounds(int row, int col) const {
+ return row >= 0 && col >= 0 && row < nRows && col < nCols;
+}
+
+template <typename ValueType>
+ValueType Grid<ValueType>::get(int row, int col) {
+ if (!inBounds(row, col)) error("get: Grid indices out of bounds");
+ return elements[(row * nCols) + col];
+}
+
+template <typename ValueType>
+const ValueType & Grid<ValueType>::get(int row, int col) const {
+ if (!inBounds(row, col)) error("get: Grid indices out of bounds");
+ return elements[(row * nCols) + col];
+}
+
+template <typename ValueType>
+void Grid<ValueType>::set(int row, int col, ValueType value) {
+ if (!inBounds(row, col)) error("set: Grid indices out of bounds");
+ elements[(row * nCols) + col] = value;
+}
+
+template <typename ValueType>
+typename Grid<ValueType>::GridRow Grid<ValueType>::operator[](int row) {
+ return GridRow(this, row);
+}
+
+template <typename ValueType>
+const typename Grid<ValueType>::GridRow
+ Grid<ValueType>::operator[](int row) const {
+ return GridRow(this, row);
+}
+
+template <typename ValueType>
+void Grid<ValueType>::mapAll(void (*fn)(ValueType value)) const {
+ for (int i = 0; i < nRows; i++) {
+ for (int j = 0; j < nCols; j++) {
+ fn(get(i, j));
+ }
+ }
+}
+
+template <typename ValueType>
+void Grid<ValueType>::mapAll(void (*fn)(const ValueType & value)) const {
+ for (int i = 0; i < nRows; i++) {
+ for (int j = 0; j < nCols; j++) {
+ fn(get(i, j));
+ }
+ }
+}
+
+template <typename ValueType>
+template <typename FunctorType>
+void Grid<ValueType>::mapAll(FunctorType fn) const {
+ for (int i = 0; i < nRows; i++) {
+ for (int j = 0; j < nCols; j++) {
+ fn(get(i, j));
+ }
+ }
+}
+
+template <typename ValueType>
+std::string Grid<ValueType>::toString() {
+ ostringstream os;
+ os << *this;
+ return os.str();
+}
+
+/*
+ * Implementation notes: << and >>
+ * -------------------------------
+ * The insertion and extraction operators use the template facilities in
+ * strlib.h to read and write generic values in a way that treats strings
+ * specially.
+ */
+
+template <typename ValueType>
+std::ostream & operator<<(std::ostream & os, const Grid<ValueType> & grid) {
+ os << "{";
+ int nRows = grid.numRows();
+ int nCols = grid.numCols();
+ for (int i = 0; i < nRows; i++) {
+ if (i > 0) os << ", ";
+ os << "{";
+ for (int j = 0; j < nCols; j++) {
+ if (j > 0) os << ", ";
+ writeGenericValue(os, grid.get(i, j), true);
+ }
+ os << "}";
+ }
+ return os << "}";
+}
+
+template <typename ValueType>
+std::istream & operator>>(std::istream & is, Grid<ValueType> & grid) {
+ Vector< Vector<ValueType> > vec2d;
+ is >> vec2d;
+ int nRows = vec2d.size();
+ int nCols = (nRows == 0) ? 0 : vec2d[0].size();
+ grid.resize(nRows, nCols);
+ for (int i = 0; i < nRows; i++) {
+ for (int j = 0; j < nCols; j++) {
+ grid[i][j] = vec2d[i][j];
+ }
+ }
+ return is;
+}
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/gtimer.cpp b/labb8/lib/StanfordCPPLib/gtimer.cpp
new file mode 100755
index 0000000..20e160d
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gtimer.cpp
@@ -0,0 +1,62 @@
+/*
+ * File: gtimer.cpp
+ * ----------------
+ * This file implements the gtimer.h interface.
+ */
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include "platform.h"
+using namespace std;
+
+/* Global variables */
+
+static Platform *pp = getPlatform();
+
+/* Implementation of the GTimer class */
+
+GTimer::GTimer(double milliseconds) {
+ gtd = new GTimerData();
+ gtd->refCount = 1;
+ pp->createTimer(*this, milliseconds);
+}
+
+GTimer::~GTimer() {
+ if (--gtd->refCount == 0) delete gtd;
+}
+
+void GTimer::start() {
+ pp->startTimer(*this);
+}
+
+void GTimer::stop() {
+ pp->stopTimer(*this);
+}
+
+bool GTimer::operator==(GTimer t2) {
+ return gtd == t2.gtd;
+}
+
+bool GTimer::operator!=(GTimer t2) {
+ return gtd != t2.gtd;
+}
+
+GTimer::GTimer(GTimerData *gtd) {
+ this->gtd = gtd;
+ gtd->refCount++;
+}
+
+GTimer::GTimer(const GTimer & src) {
+ this->gtd = src.gtd;
+ this->gtd->refCount++;
+}
+
+GTimer & GTimer::operator=(const GTimer & src) {
+ if (this != &src) {
+ if (--gtd->refCount == 0) delete gtd;
+ this->gtd = src.gtd;
+ this->gtd->refCount++;
+ }
+ return *this;
+}
diff --git a/labb8/lib/StanfordCPPLib/gtimer.h b/labb8/lib/StanfordCPPLib/gtimer.h
new file mode 100755
index 0000000..a0a6d7d
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gtimer.h
@@ -0,0 +1,116 @@
+/*
+ * File: gtimer.h
+ * --------------
+ * This file defines the <code>GTimer</code> class, which implements a
+ * general interval timer.
+ */
+
+#ifndef _gtimer_h
+#define _gtimer_h
+
+#include <string>
+
+/*
+ * Friend type: GTimerData
+ * -----------------------
+ * This type maintains a reference count to determine when it is
+ * possible to free the timer. The address of this block is used
+ * as the timer id.
+ */
+
+struct GTimerData {
+ int refCount;
+};
+
+/*
+ * Class: GTimer
+ * -------------
+ * This class implements a simple interval timer that generates a
+ * <code>GTimerEvent</code> with a specified frequency. Copying
+ * a <code>GTimer</code> object is legal and creates an object that
+ * refers to the same internal timer.
+ */
+
+class GTimer {
+
+public:
+
+/*
+ * Constructor: GTimer
+ * Usage: GTimer timer(milliseconds);
+ * ----------------------------------
+ * Creates a timer object that generates a <code>GTimerEvent</code>
+ * each time the specified number of milliseconds has elapsed. No
+ * events are generated until the client calls <code>start</code>
+ * on the timer. For more details on using timers, see the documentation
+ * for the <a href="GTimerEvent-class.html"><code>GTimerEvent</code></a>
+ * class.
+ */
+
+ GTimer(double milliseconds);
+
+/*
+ * Destructor: ~GTimer
+ * -------------------
+ * Frees the resources associated with the timer.
+ */
+
+ virtual ~GTimer();
+
+/*
+ * Method: start
+ * Usage: timer.start();
+ * ---------------------
+ * Starts the timer. A timer continues to generate timer events until it
+ * is stopped; to achieve the effect of a one-shot timer, the simplest
+ * approach is to call the <code>stop</code> method inside the event
+ * handler.
+ */
+
+ void start();
+
+/*
+ * Method: stop
+ * Usage: timer.stop();
+ * --------------------
+ * Stops the timer so that it stops generating events until it is restarted.
+ */
+
+ void stop();
+
+/*
+ * Friend operator: ==
+ * Usage: if (t1 == t2) ...
+ * ------------------------
+ * Checks whether the two objects refer to the same timer.
+ */
+
+ bool operator==(GTimer t2);
+
+/*
+ * Friend operator: !=
+ * Usage: if (t1 != t2) ...
+ * ------------------------
+ * Checks whether the two objects refer to the different timers.
+ */
+
+ bool operator!=(GTimer t2);
+
+/* Private section */
+
+ GTimer(GTimerData *gtd);
+ GTimer(const GTimer & src);
+ GTimer & operator=(const GTimer & src);
+
+private:
+
+/* Instance variables */
+
+ GTimerData *gtd;
+
+ friend class Platform;
+ friend class GTimerEvent;
+
+};
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/gtypes.cpp b/labb8/lib/StanfordCPPLib/gtypes.cpp
new file mode 100755
index 0000000..2e5c678
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gtypes.cpp
@@ -0,0 +1,196 @@
+/*
+ * File: gtypes.cpp
+ * ----------------
+ * This file implements the classes in the gtypes.h interface.
+ */
+
+#include <string>
+#include <cmath>
+#include "error.h"
+#include "gtypes.h"
+#include "strlib.h"
+using namespace std;
+
+static const double PI = 3.14159265358979;
+static const int HASH_MASK = int(unsigned(-1) >> 1);
+
+/*
+ * Implementation notes: GPoint class
+ * ----------------------------------
+ * The GPoint class itself is entirely straightforward. The relational
+ * operators compare the x components first, followed by the y component.
+ * The hashCode function computes the exclusive-or of the individual words.
+ */
+
+GPoint::GPoint() {
+ x = 0;
+ y = 0;
+}
+
+GPoint::GPoint(double x, double y) {
+ this->x = x;
+ this->y = y;
+}
+
+double GPoint::getX() const {
+ return x;
+}
+
+double GPoint::getY() const {
+ return y;
+}
+
+string GPoint::toString() const {
+ return "(" + realToString(x) + ", " + realToString(y) + ")";
+}
+
+ostream & operator<<(ostream & os, const GPoint & pt) {
+ return os << pt.toString();
+}
+
+bool operator==(const GPoint & p1, const GPoint & p2) {
+ return p1.x == p2.x && p1.y == p2.y;
+}
+
+bool operator!=(const GPoint & p1, const GPoint & p2) {
+ return !(p1 == p2);
+}
+
+int hashCode(const GPoint & pt) {
+ int hash = 0;
+ for (size_t i = 0; i < sizeof(double) / sizeof(int); i++) {
+ hash ^= ((int *) &pt.x)[i] ^ ((int *) &pt.y)[i];
+ }
+ return HASH_MASK & hash;
+}
+
+/*
+ * Implementation notes: GDimension class
+ * --------------------------------------
+ * The GDimension class itself is entirely straightforward. The
+ * relational operators compare the width first, followed by the height.
+ * The hashCode function computes the exclusive-or of the individual words.
+ */
+
+GDimension::GDimension() {
+ width = 0;
+ height = 0;
+}
+
+GDimension::GDimension(double width, double height) {
+ this->width = width;
+ this->height = height;
+}
+
+double GDimension::getWidth() const {
+ return width;
+}
+
+double GDimension::getHeight() const {
+ return height;
+}
+
+string GDimension::toString() const {
+ return "(" + realToString(width) + ", " + realToString(height) + ")";
+}
+
+ostream & operator<<(ostream & os, const GDimension & dim) {
+ return os << dim.toString();
+}
+
+bool operator==(const GDimension & d1, const GDimension & d2) {
+ return d1.width == d2.width && d1.height == d2.height;
+}
+
+bool operator!=(const GDimension & d1, const GDimension & d2) {
+ return !(d1 == d2);
+}
+
+int hashCode(const GDimension & dim) {
+ int hash = 0;
+ for (size_t i = 0; i < sizeof(double) / sizeof(int); i++) {
+ hash ^= ((int *) &dim.width)[i] ^ ((int *) &dim.height)[i];
+ }
+ return HASH_MASK & hash;
+}
+
+/*
+ * Implementation notes: GRectangle class
+ * --------------------------------------
+ * The GRectangle class itself is entirely straightforward. The
+ * relational operators compare the components in the following order:
+ * x, y, width, height. The hashCode function computes the exclusive-or
+ * of the individual words.
+ */
+
+GRectangle::GRectangle() {
+ x = 0;
+ y = 0;
+ width = 0;
+ height = 0;
+}
+
+GRectangle::GRectangle(double x, double y, double width, double height) {
+ this->x = x;
+ this->y = y;
+ this->width = width;
+ this->height = height;
+}
+
+double GRectangle::getX() const {
+ return x;
+}
+
+double GRectangle::getY() const {
+ return y;
+}
+
+double GRectangle::getWidth() const {
+ return width;
+}
+
+double GRectangle::getHeight() const {
+ return height;
+}
+
+bool GRectangle::isEmpty() const {
+ return width <= 0 || height <= 0;
+}
+
+bool GRectangle::contains(double x, double y) const {
+ return x >= this->x && y >= this->y
+ && x < this->x + width
+ && y < this->y + height;
+}
+
+bool GRectangle::contains(GPoint pt) const {
+ return contains(pt.getX(), pt.getY());
+}
+
+string GRectangle::toString() const {
+ return "(" + realToString(x) + ", " + realToString(y) + ", "
+ + realToString(width) + ", " + realToString(height) + ")";
+}
+
+ostream & operator<<(ostream & os, const GRectangle & rect) {
+ return os << rect.toString();
+}
+
+bool operator==(const GRectangle & r1, const GRectangle & r2) {
+ return r1.x == r2.x && r1.y == r2.y
+ && r1.width == r2.width
+ && r1.height == r2.height;
+}
+
+bool operator!=(const GRectangle & r1, const GRectangle & r2) {
+ return !(r1 == r2);
+}
+
+int hashCode(const GRectangle & r) {
+ int hash = 0;
+ for (size_t i = 0; i < sizeof(double) / sizeof(int); i++) {
+ hash ^= ((int *) &r.x)[i] ^ ((int *) &r.y)[i];
+ hash ^= ((int *) &r.width)[i] ^ ((int *) &r.height)[i];
+ }
+ return HASH_MASK & hash;
+}
diff --git a/labb8/lib/StanfordCPPLib/gtypes.h b/labb8/lib/StanfordCPPLib/gtypes.h
new file mode 100755
index 0000000..cd55b53
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gtypes.h
@@ -0,0 +1,301 @@
+/*
+ * File: gtypes.h
+ * --------------
+ * This file defines classes for representing points, dimensions, and
+ * rectangles.
+ */
+
+#ifndef _gtypes_h
+#define _gtypes_h
+
+#include <iostream>
+#include <string>
+
+/*
+ * Class: GPoint
+ * -------------
+ * This class contains real-valued x and y fields. It is used to
+ * represent a location on the graphics plane.
+ */
+
+class GPoint {
+
+public:
+
+/*
+ * Constructor: GPoint
+ * Usage: GPoint origin;
+ * GPoint pt(x, y);
+ * -----------------------
+ * Creates a <code>GPoint</code> object with the specified <code>x</code>
+ * and <code>y</code> coordinates. If the coordinates are not supplied,
+ * the default constructor sets these fields to 0.
+ */
+
+ GPoint();
+ GPoint(double x, double y);
+
+/*
+ * Method: getX
+ * Usage: double x = pt.getX();
+ * ----------------------------
+ * Returns the x component of the point.
+ */
+
+ double getX() const;
+
+/*
+ * Method: getY
+ * Usage: double y = pt.getY();
+ * ----------------------------
+ * Returns the y component of the point.
+ */
+
+ double getY() const;
+
+/*
+ * Method: toString
+ * Usage: string str = pt.toString();
+ * ----------------------------------
+ * Converts the <code>GPoint</code> to a string in the form
+ * <code>"(</code><i>x</i><code>,</code>&nbsp;<i>y</i><code>)"</code>.
+ */
+
+ std::string toString() const;
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in this class is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+private:
+
+/* Instance variables */
+
+ double x; /* The x-coordinate of the point */
+ double y; /* The y-coordinate of the point */
+
+/* Friend declarations */
+
+ friend bool operator==(const GPoint & p1, const GPoint & p2);
+ friend bool operator!=(const GPoint & p1, const GPoint & p2);
+ friend int hashCode(const GPoint & pt);
+
+};
+
+/*
+ * Class: GDimension
+ * -----------------
+ * This class contains real-valued width and height fields. It is used
+ * to indicate the size of a graphical object.
+ */
+
+class GDimension {
+
+public:
+
+/*
+ * Constructor: GDimension
+ * Usage: GDimension empty;
+ * GDimension dim(width, height);
+ * -------------------------------------
+ * Creates a <code>GDimension</code> object with the specified
+ * <code>width</code> and <code>height</code> coordinates. If the
+ * coordinates are not supplied, the default constructor sets these
+ * fields to 0.
+ */
+
+ GDimension();
+ GDimension(double width, double height);
+
+/*
+ * Method: getWidth
+ * Usage: double width = dim.getWidth();
+ * -------------------------------------
+ * Returns the width component of the <code>GDimension</code> object.
+ */
+
+ double getWidth() const;
+
+/*
+ * Method: getHeight
+ * Usage: double height = dim.getHeight();
+ * ---------------------------------------
+ * Returns the height component of the <code>GDimension</code> object.
+ */
+
+ double getHeight() const;
+
+/*
+ * Method: toString
+ * Usage: string str = dim.toString();
+ * -----------------------------------
+ * Converts the <code>GDimension</code> to a string in the form
+ * <code>"(</code><i>width</i><code>,</code>&nbsp;<i>height</i><code>)"</code>.
+ */
+
+ std::string toString() const;
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in this class is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+private:
+
+/* Instance variables */
+
+ double width; /* The width of the GDimension */
+ double height; /* The height of the GDimension */
+
+/* Friend declarations */
+
+ friend bool operator==(const GDimension & d1, const GDimension & d2);
+ friend bool operator!=(const GDimension & d1, const GDimension & d2);
+ friend int hashCode(const GDimension & dim);
+
+};
+
+/*
+ * Class: GRectangle
+ * -----------------
+ * This type contains real-valued x, y, width, and height fields. It is
+ * used to represent the bounding box of a graphical object.
+ */
+
+class GRectangle {
+
+public:
+
+/*
+ * Constructor: GRectangle
+ * Usage: GRectangle empty;
+ * GRectangle r(x, y, width, height);
+ * -----------------------------------------
+ * Creates a <code>GRectangle</code> object with the specified components.
+ * If these parameters are not supplied, the default constructor sets
+ * these fields to 0.
+ */
+
+ GRectangle();
+ GRectangle(double x, double y, double width, double height);
+
+/*
+ * Method: getX
+ * Usage: double x = r.getX();
+ * ---------------------------
+ * Returns the x component of the rectangle.
+ */
+
+ double getX() const;
+
+/*
+ * Method: getY
+ * Usage: double y = pt.getY();
+ * ----------------------------
+ * Returns the y component of the rectangle.
+ */
+
+ double getY() const;
+
+/*
+ * Method: getWidth
+ * Usage: double width = r.getWidth();
+ * -----------------------------------
+ * Returns the width component of the rectangle.
+ */
+
+ double getWidth() const;
+
+/*
+ * Method: getHeight
+ * Usage: double height = pt.getHeight();
+ * --------------------------------------
+ * Returns the height component of the rectangle.
+ */
+
+ double getHeight() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (r.isEmpty()) ...
+ * ---------------------------
+ * Returns <code>true</code> if the rectangle is empty.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: contains
+ * Usage: if (r.contains(pt)) ...
+ * if (r.contains(x, y)) ...
+ * --------------------------------
+ * Returns <code>true</code> if the rectangle contains the given point,
+ * which may be specified either as a point or as distinct coordinates.
+ */
+
+ bool contains(GPoint pt) const;
+ bool contains(double x, double y) const;
+
+/*
+ * Method: toString
+ * Usage: string str = r.toString();
+ * ---------------------------------
+ * Converts the <code>GRectangle</code> to a string in the form
+ * <code>"(</code><i>x</i><code>,</code>&nbsp;<i>y</i><code>,</code>
+ * <i>width</i><code>,</code>&nbsp;<i>height</i><code>)"</code>.
+ */
+
+ std::string toString() const;
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in this class is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+private:
+
+/* Instance variables */
+
+ double x; /* The x-coordinate of the rectangle */
+ double y; /* The y-coordinate of the rectangle */
+ double width; /* The width of the rectangle */
+ double height; /* The height of the rectangle */
+
+/* Friend declarations */
+
+ friend bool operator==(const GRectangle & r1, const GRectangle & r2);
+ friend bool operator!=(const GRectangle & r1, const GRectangle & r2);
+ friend int hashCode(const GRectangle & r);
+
+};
+
+/*
+ * Free functions
+ * --------------
+ * This section of the interface defines the insertion, comparison,
+ * and hashCode functions for the geometric types.
+ */
+
+std::ostream & operator<<(std::ostream & os, const GPoint & pt);
+bool operator==(const GPoint & p1, const GPoint & p2);
+bool operator!=(const GPoint & p1, const GPoint & p2);
+int hashCode(const GPoint & pt);
+
+std::ostream & operator<<(std::ostream & os, const GDimension & dim);
+bool operator==(const GDimension & d1, const GDimension & d2);
+bool operator!=(const GDimension & d1, const GDimension & d2);
+int hashCode(const GDimension & dim);
+
+std::ostream & operator<<(std::ostream & os, const GRectangle & rect);
+bool operator==(const GRectangle & r1, const GRectangle & r2);
+bool operator!=(const GRectangle & r1, const GRectangle & r2);
+int hashCode(const GRectangle & r);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/gwindow.cpp b/labb8/lib/StanfordCPPLib/gwindow.cpp
new file mode 100755
index 0000000..30c9ea8
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gwindow.cpp
@@ -0,0 +1,355 @@
+/*
+ * File: gwindow.cpp
+ * -----------------
+ * This file implements the GWindow class, passing most calls directly
+ * to the appropriate methods in the Platform class, which is implemented
+ * separately for each architecture.
+ */
+
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include "gevents.h"
+#include "gobjects.h"
+#include "gmath.h"
+#include "gtypes.h"
+#include "gwindow.h"
+#include "map.h"
+#include "strlib.h"
+#include "vector.h"
+#include "platform.h"
+using namespace std;
+
+/* Constants */
+
+static const int DEFAULT_WIDTH = 500;
+static const int DEFAULT_HEIGHT = 300;
+
+/* Private function prototypes */
+
+static void initColorTable();
+static string canonicalColorName(string str);
+
+/*
+ * Global variable: pp
+ * -------------------
+ * This variable points to a singleton of the Platform class.
+ */
+
+static Platform *pp = getPlatform();
+
+/*
+ * Global variable: colorTable
+ * ---------------------------
+ * This variable holds the translation table that maps colors into
+ * their RGB values. This color table is shared throughout the
+ * application and cannot be manipulated by any clients. If you
+ * need to define color names for application specific colors, you
+ * should do so by defining string constants with the appropriate
+ * hexadecimal values, as in
+ *
+ * const string MAGENTA = "0xFF00FF";
+ */
+
+static Map<string,int> colorTable;
+
+GWindow::GWindow() {
+ initGWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, true);
+}
+
+GWindow::GWindow(bool visible) {
+ initGWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, visible);
+}
+
+GWindow::GWindow(double width, double height) {
+ initGWindow(width, height, true);
+}
+
+GWindow::GWindow(double width, double height, bool visible) {
+ initGWindow(width, height, visible);
+}
+
+void GWindow::initGWindow(double width, double height, bool visible) {
+ gwd = new GWindowData();
+ gwd->windowWidth = width;
+ gwd->windowHeight = height;
+ gwd->top = new GCompound();
+ pp->createGWindow(*this, width, height, gwd->top);
+ setColor("BLACK");
+ setVisible(visible);
+ pause(1000); // Temporary fix for race condition in back-end.
+}
+
+GWindow::~GWindow() {
+ /* Empty */
+}
+
+void GWindow::close() {
+ pp->close(*this);
+ pp->deleteGWindow(*this);
+}
+
+void GWindow::requestFocus() {
+ pp->requestFocus(*this);
+}
+
+void GWindow::clear() {
+ gwd->top->removeAll();
+ pp->clear(*this);
+}
+
+void GWindow::repaint() {
+ pp->repaint(*this);
+}
+
+void GWindow::setVisible(bool flag) {
+ gwd->visible = flag;
+ pp->setVisible(*this, flag);
+}
+
+bool GWindow::isVisible() {
+ return gwd->visible;
+}
+
+void GWindow::drawLine(const GPoint & p0, const GPoint & p1) {
+ drawLine(p0.getX(), p0.getY(), p1.getX(), p1.getY());
+}
+
+void GWindow::drawLine(double x0, double y0, double x1, double y1) {
+ GLine line(x0, y0, x1, y1);
+ line.setColor(gwd->color);
+ draw(line);
+}
+
+GPoint GWindow::drawPolarLine(const GPoint & p0, double r, double theta) {
+ return drawPolarLine(p0.getX(), p0.getY(), r, theta);
+}
+
+GPoint GWindow::drawPolarLine(double x0, double y0, double r, double theta) {
+ double x1 = x0 + r * cosDegrees(theta);
+ double y1 = y0 - r * sinDegrees(theta);
+ drawLine(x0, y0, x1, y1);
+ return GPoint(x1, y1);
+}
+
+void GWindow::drawRect(const GRectangle & bounds) {
+ drawRect(bounds.getX(), bounds.getY(), bounds.getWidth(),
+ bounds.getHeight());
+}
+
+void GWindow::drawRect(double x, double y, double width, double height) {
+ GRect rect(x, y, width, height);
+ rect.setColor(gwd->color);
+ draw(rect);
+}
+
+void GWindow::fillRect(const GRectangle & bounds) {
+ fillRect(bounds.getX(), bounds.getY(), bounds.getWidth(),
+ bounds.getHeight());
+}
+
+void GWindow::fillRect(double x, double y, double width, double height) {
+ GRect rect(x, y, width, height);
+ rect.setColor(gwd->color);
+ rect.setFilled(true);
+ draw(rect);
+}
+
+void GWindow::drawOval(const GRectangle & bounds) {
+ drawOval(bounds.getX(), bounds.getY(), bounds.getWidth(),
+ bounds.getHeight());
+}
+
+void GWindow::drawOval(double x, double y, double width, double height) {
+ GOval oval(x, y, width, height);
+ oval.setColor(gwd->color);
+ draw(oval);
+}
+
+void GWindow::fillOval(const GRectangle & bounds) {
+ fillOval(bounds.getX(), bounds.getY(), bounds.getWidth(),
+ bounds.getHeight());
+}
+
+void GWindow::fillOval(double x, double y, double width, double height) {
+ GOval oval(x, y, width, height);
+ oval.setColor(gwd->color);
+ oval.setFilled(true);
+ draw(oval);
+}
+
+void GWindow::setColor(string color) {
+ setColor(convertColorToRGB(color));
+}
+
+void GWindow::setColor(int rgb) {
+ gwd->color = convertRGBToColor(rgb);
+}
+
+string GWindow::getColor() {
+ return gwd->color;
+}
+
+double GWindow::getWidth() {
+ return gwd->windowWidth;
+}
+
+double GWindow::getHeight() {
+ return gwd->windowHeight;
+}
+
+void GWindow::setWindowTitle(string title) {
+ gwd->windowTitle = title;
+ pp->setWindowTitle(*this, title);
+}
+
+string GWindow::getWindowTitle() {
+ return gwd->windowTitle;
+}
+
+void GWindow::draw(const GObject & gobj) {
+ draw(&gobj);
+}
+
+void GWindow::draw(GObject *gobj) {
+ pp->draw(*this, gobj);
+}
+
+void GWindow::draw(const GObject *gobj) {
+ pp->draw(*this, gobj);
+}
+
+void GWindow::draw(GObject & gobj, double x, double y) {
+ draw(&gobj, x, y);
+}
+
+void GWindow::draw(GObject *gobj, double x, double y) {
+ gobj->setLocation(x, y);
+ pp->draw(*this, gobj);
+}
+
+void GWindow::add(GObject *gobj) {
+ gwd->top->add(gobj);
+}
+
+void GWindow::add(GObject *gobj, double x, double y) {
+ gobj->setLocation(x, y);
+ add(gobj);
+}
+
+void GWindow::addToRegion(GInteractor *gobj, string region) {
+ pp->addToRegion(*this, (GObject *) gobj, region);
+}
+
+void GWindow::addToRegion(GLabel *gobj, string region) {
+ pp->addToRegion(*this, (GObject *) gobj, region);
+}
+
+void GWindow::removeFromRegion(GInteractor *gobj, string region) {
+ pp->removeFromRegion(*this, (GObject *) gobj, region);
+}
+
+void GWindow::removeFromRegion(GLabel *gobj, string region) {
+ pp->removeFromRegion(*this, (GObject *) gobj, region);
+}
+
+void GWindow::remove(GObject *gobj) {
+ gwd->top->remove(gobj);
+}
+
+GObject *GWindow::getGObjectAt(double x, double y) {
+ int n = gwd->top->getElementCount();
+ for (int i = n - 1; i >= 0; i--) {
+ GObject *gobj = gwd->top->getElement(i);
+ if (gobj->contains(x, y)) return gobj;
+ }
+ return NULL;
+}
+
+void GWindow::setRegionAlignment(string region, string align) {
+ pp->setRegionAlignment(*this, region, align);
+}
+
+bool GWindow::operator==(GWindow w2) {
+ return gwd == w2.gwd;
+}
+
+bool GWindow::operator!=(GWindow w2) {
+ return gwd != w2.gwd;
+}
+
+GWindow::GWindow(GWindowData *gwd) {
+ this->gwd = gwd;
+}
+
+void pause(double milliseconds) {
+ pp->pause(milliseconds);
+}
+
+double getScreenWidth() {
+ return pp->getScreenWidth();
+}
+
+double getScreenHeight() {
+ return pp->getScreenWidth();
+}
+
+int convertColorToRGB(string colorName) {
+ if (colorName == "") return -1;
+ if (colorName[0] == '#') {
+ istringstream is(colorName.substr(1) + "@");
+ int rgb;
+ char terminator = '\0';
+ is >> hex >> rgb >> terminator;
+ if (terminator != '@') error("setColor: Illegal color - " + colorName);
+ return rgb;
+ }
+ string name = canonicalColorName(colorName);
+ if (colorTable.size() == 0) initColorTable();
+ if (!colorTable.containsKey(name)) {
+ error("setColor: Undefined color - " + colorName);
+ }
+ return colorTable[name];
+}
+
+string convertRGBToColor(int rgb) {
+ if (rgb == -1) return "";
+ ostringstream os;
+ os << hex << setfill('0') << uppercase << "#";
+ os << setw(2) << (rgb >> 16 & 0xFF);
+ os << setw(2) << (rgb >> 8 & 0xFF);
+ os << setw(2) << (rgb & 0xFF);
+ return os.str();
+}
+
+void exitGraphics() {
+ pp->exitGraphics();
+ exit(0);
+}
+
+static void initColorTable() {
+ colorTable["black"] = 0x000000;
+ colorTable["darkgray"] = 0x595959;
+ colorTable["gray"] = 0x999999;
+ colorTable["lightgray"] = 0xBFBFBF;
+ colorTable["white"] = 0xFFFFFF;
+ colorTable["red"] = 0xFF0000;
+ colorTable["yellow"] = 0xFFFF00;
+ colorTable["green"] = 0x00FF00;
+ colorTable["cyan"] = 0x00FFFF;
+ colorTable["blue"] = 0x0000FF;
+ colorTable["magenta"] = 0xFF00FF;
+ colorTable["orange"] = 0xFFC800;
+ colorTable["pink"] = 0xFFAFAF;
+}
+
+static string canonicalColorName(string str) {
+ string result = "";
+ int nChars = str.length();
+ for (int i = 0; i < nChars; i++) {
+ char ch = str[i];
+ if (!isspace(ch) && ch != '_') result += tolower(ch);
+ }
+ return result;
+}
diff --git a/labb8/lib/StanfordCPPLib/gwindow.h b/labb8/lib/StanfordCPPLib/gwindow.h
new file mode 100755
index 0000000..e6dbfbd
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/gwindow.h
@@ -0,0 +1,536 @@
+/*
+ * File: gwindow.h
+ * ---------------
+ * This file defines the <code>GWindow</code> class which supports
+ * drawing graphical objects on the screen.
+ */
+
+#ifndef _gwindow_h
+#define _gwindow_h
+
+#include <string>
+#include "gtypes.h"
+#include "vector.h"
+
+class GCompound;
+class GInteractor;
+class GLabel;
+class GObject;
+
+/*
+ * Friend type: GWindowData
+ * ------------------------
+ * This block contains all data pertaining to the window. Shallow copying
+ * of the <code>GWindow</code> object ensures that all copies refer to the
+ * same onscreen window.
+ */
+
+struct GWindowData {
+ double windowWidth;
+ double windowHeight;
+ std::string windowTitle;
+ std::string color;
+ bool visible;
+ GCompound *top;
+};
+
+/*
+ * Class: GWindow
+ * --------------
+ * This class represents a graphics window that supports simple graphics.
+ * Each <code>GWindow</code> consists of two layers. The background layer
+ * provides a surface for drawing static pictures that involve no animation.
+ * Graphical objects drawn in the background layer are persistent and do
+ * not require the client to update the contents of the window. The
+ * foreground layer contains graphical objects that are redrawn as necessary.
+ *
+ * <p>The <code>GWindow</code> class includes several methods that draw
+ * lines, rectangles, and ovals on the background layer without making
+ * use of the facilities of the <code>gobjects.h</code> interface. For
+ * example, the following program draws a diamond, rectangle, and oval
+ * at the center of the window.
+ *
+ *<pre>
+ * int main() {
+ * GWindow gw;
+ * cout << "This program draws a diamond, rectangle, and oval." << endl;
+ * double width = gw.getWidth();
+ * double height = gw.getHeight();
+ * gw.drawLine(0, height / 2, width / 2, 0);
+ * gw.drawLine(width / 2, 0, width, height / 2);
+ * gw.drawLine(width, height / 2, width / 2, height);
+ * gw.drawLine(width / 2, height, 0, height / 2);
+ * gw.setColor("BLUE");
+ * gw.fillRect(width / 4, height / 4, width / 2, height / 2);
+ * gw.setColor("GRAY");
+ * gw.fillOval(width / 4, height / 4, width / 2, height / 2);
+ * return 0;
+ * }
+ *</pre>
+ *
+ * A <code>GWindow</code> object may be freely copied, after which all
+ * copies refer to the same window.
+ */
+
+class GWindow {
+
+public:
+
+/*
+ * Constructor: GWindow
+ * Usage: GWindow gw;
+ * GWindow gw(width, height);
+ * ---------------------------------
+ * Creates a window, either of the specified size or a default size.
+ */
+
+ GWindow();
+ GWindow(double width, double height);
+
+/*
+ * Destructor: ~GWindow
+ * --------------------
+ * Reclaims the internal storage for the window. Note that the window
+ * is not closed by this operation, but persists until it is closed by
+ * the client or the user exits the program.
+ */
+
+ virtual ~GWindow();
+
+/*
+ * Method: close
+ * Usage: gw.close();
+ * ------------------
+ * Deletes the window from the screen.
+ */
+
+ void close();
+
+/*
+ * Method: requestFocus
+ * Usage: gw.requestFocus();
+ * -------------------------
+ * Asks the system to assign the keyboard focus to the window, which
+ * brings it to the top and ensures that key events are delivered to
+ * the window. Clicking in the window automatically requests the focus.
+ */
+
+ void requestFocus();
+
+/*
+ * Method: clear
+ * Usage: gw.clear();
+ * ------------------
+ * Clears the contents of the window.
+ */
+
+ void clear();
+
+/*
+ * Method: setVisible
+ * Usage: gw.setVisible(flag);
+ * ---------------------------
+ * Determines whether the window is visible on the screen.
+ */
+
+ void setVisible(bool flag);
+
+/*
+ * Method: isVisible
+ * Usage: if (gw.isVisible()) ...
+ * ------------------------------
+ * Tests whether the window is visible.
+ */
+
+ bool isVisible();
+
+/*
+ * Method: drawLine
+ * Usage: gw.drawLine(p0, p1);
+ * gw.drawLine(x0, y0, x1, y1);
+ * -----------------------------------
+ * Draws a line connecting the specified points.
+ */
+
+ void drawLine(const GPoint & p0, const GPoint & p1);
+ void drawLine(double x0, double y0, double x1, double y1);
+
+/*
+ * Method: drawPolarLine
+ * Usage: GPoint p1 = gw.drawPolarLine(p0, r, theta);
+ * GPoint p1 = gw.drawPolarLine(x0, y0, r, theta);
+ * ------------------------------------------------------
+ * Draws a line of length <code>r</code> in the direction <code>theta</code>
+ * from the initial point. The angle <code>theta</code> is measured in
+ * degrees counterclockwise from the +<i>x</i> axis. The method returns
+ * the end point of the line.
+ */
+
+ GPoint drawPolarLine(const GPoint & p0, double r, double theta);
+ GPoint drawPolarLine(double x0, double y0, double r, double theta);
+
+/*
+ * Method: drawOval
+ * Usage: gw.drawOval(bounds);
+ * gw.drawOval(x, y, width, height);
+ * ----------------------------------------
+ * Draws the frame of a oval with the specified bounds.
+ */
+
+ void drawOval(const GRectangle & bounds);
+ void drawOval(double x, double y, double width, double height);
+
+/*
+ * Method: fillOval
+ * Usage: gw.fillOval(bounds);
+ * gw.fillOval(x, y, width, height);
+ * ----------------------------------------
+ * Fills the frame of a oval with the specified bounds.
+ */
+
+ void fillOval(const GRectangle & bounds);
+ void fillOval(double x, double y, double width, double height);
+
+/*
+ * Method: drawRect
+ * Usage: gw.drawRect(bounds);
+ * gw.drawRect(x, y, width, height);
+ * ----------------------------------------
+ * Draws the frame of a rectangle with the specified bounds.
+ */
+
+ void drawRect(const GRectangle & bounds);
+ void drawRect(double x, double y, double width, double height);
+
+/*
+ * Method: fillRect
+ * Usage: gw.fillRect(bounds);
+ * gw.fillRect(x, y, width, height);
+ * ----------------------------------------
+ * Fills the frame of a rectangle with the specified bounds.
+ */
+
+ void fillRect(const GRectangle & bounds);
+ void fillRect(double x, double y, double width, double height);
+
+/*
+ * Method: setColor
+ * Usage: gw.setColor(color);
+ * --------------------------
+ * Sets the color used for drawing. The <code>color</code> parameter is
+ * usually one of the predefined color names:
+ *
+ * <code>BLACK</code>,
+ * <code>BLUE</code>,
+ * <code>CYAN</code>,
+ * <code>DARK_GRAY</code>,
+ * <code>GRAY</code>,
+ * <code>GREEN</code>,
+ * <code>LIGHT_GRAY</code>,
+ * <code>MAGENTA</code>,
+ * <code>ORANGE</code>,
+ * <code>PINK</code>,
+ * <code>RED</code>,
+ * <code>WHITE</code>, and
+ * <code>YELLOW</code>.
+ *
+ * The case of the individual letters in the color name is ignored, as
+ * are spaces and underscores, so that the color <code>DARK_GRAY</code>
+ * can be written as <code>"Dark Gray"</code>.
+ *
+ * <p>The color can also be specified as a string in the form
+ * <code>"#rrggbb"</code> where <code>rr</code>, <code>gg</code>, and
+ * <code>bb</code> are pairs of hexadecimal digits indicating the
+ * red, green, and blue components of the color.
+ */
+
+ void setColor(std::string color);
+ void setColor(int color);
+
+/*
+ * Method: getColor
+ * Usage: string color = gw.getColor();
+ * ------------------------------------
+ * Returns the current color as a string in the form <code>"#rrggbb"</code>.
+ * In this string, the values <code>rr</code>, <code>gg</code>,
+ * and <code>bb</code> are two-digit hexadecimal values representing
+ * the red, green, and blue components of the color, respectively.
+ */
+
+ std::string getColor();
+
+/*
+ * Method: getWidth
+ * Usage: double width = gw.getWidth();
+ * ------------------------------------
+ * Returns the width of the graphics window in pixels.
+ */
+
+ double getWidth();
+
+/*
+ * Method: getHeight
+ * Usage: double height = gw.getHeight();
+ * --------------------------------------
+ * Returns the height of the graphics window in pixels.
+ */
+
+ double getHeight();
+
+/*
+ * Method: repaint
+ * Usage: gw.repaint();
+ * --------------------
+ * Schedule a repaint on this window.
+ */
+
+ void repaint();
+
+/*
+ * Method: setWindowTitle
+ * Usage: gw.setWindowTitle(title);
+ * --------------------------------
+ * Sets the title of the graphics window.
+ */
+
+ void setWindowTitle(std::string title);
+
+/*
+ * Method: getWindowTitle
+ * Usage: string title = gw.getWindowTitle();
+ * ------------------------------------------
+ * Returns the title of the graphics window.
+ */
+
+ std::string getWindowTitle();
+
+/*
+ * Method: draw
+ * Usage: gw.draw(gobj);
+ * gw.draw(gobj, x, y);
+ * ---------------------------
+ * Draws the <code>GObject</code> on the background layer. For convenience,
+ * the <code>gobj</code> parameter may be passed either as a constant
+ * reference or as a pointer. If the <code>x</code> and <code>y</code>
+ * parameters are included, the object is moved to that location before
+ * drawing.
+ */
+
+ void draw(const GObject & gobj);
+ void draw(GObject *gobj);
+ void draw(const GObject *gobj);
+ void draw(GObject & gobj, double x, double y);
+ void draw(GObject *gobj, double x, double y);
+
+/*
+ * Method: add
+ * Usage: gw.add(gobj);
+ * gw.add(gobj, x, y);
+ * --------------------------
+ * Adds the <code>GObject</code> to the foreground layer of the window.
+ * The second form of the call sets the location of the object to
+ * (<code>x</code>, <code>y</code>) first.
+ *
+ * <p>In terms of memory management, adding a <code>GObject</code> pointer to
+ * a <code>GWindow</code> transfers control of that object from the client to
+ * the window manager. Deleting a <code>GWindow</code> automatically deletes
+ * any <nobr><code>GObject</code><font size=-1>s</font></nobr> it contains.
+ */
+
+ void add(GObject *gobj);
+ void add(GObject *gobj, double x, double y);
+
+/*
+ * Method: remove
+ * Usage: gw.remove(gobj);
+ * -----------------------
+ * Removes the object from the window.
+ */
+
+ void remove(GObject *gobj);
+
+/*
+ * Method: addToRegion
+ * Usage: gw.addToRegion(interactor, region);
+ * ------------------------------------------
+ * Adds the interactor (which can also be a <code>GLabel</code>) to
+ * the control strip specified by the <code>region</code> parameter.
+ * The <code>region</code> parameter must be one of the strings
+ * <code>"NORTH"</code>, <code>"EAST"</code>, <code>"SOUTH"</code>,
+ * or <code>"WEST"</code>.
+ */
+
+ void addToRegion(GInteractor *gobj, std::string region);
+ void addToRegion(GLabel *gobj, std::string region);
+
+/*
+ * Method: removeFromRegion
+ * Usage: gw.removeFromRegion(interactor, region);
+ * -----------------------------------------------
+ * Adds the interactor (which can also be a <code>GLabel</code>) to
+ * the control strip specified by the <code>region</code> parameter.
+ * The <code>region</code> parameter must be one of the strings
+ * <code>"NORTH"</code>, <code>"EAST"</code>, <code>"SOUTH"</code>,
+ * or <code>"WEST"</code>.
+ */
+
+ void removeFromRegion(GInteractor *gobj, std::string region);
+ void removeFromRegion(GLabel *gobj, std::string region);
+
+/*
+ * Method: getGObjectAt
+ * Usage: GObject *gobj = getGObjectAt(x, y);
+ * ------------------------------------------
+ * Returns a pointer to the topmost <code>GObject</code> containing the
+ * point (<code>x</code>, <code>y</code>), or <code>NULL</code> if no such
+ * object exists.
+ */
+
+ GObject *getGObjectAt(double x, double y);
+
+/*
+ * Method: setRegionAlignment
+ * Usage: gw.setRegionAlignment(region, align);
+ * --------------------------------------------
+ * Sets the alignment of the specified side region as specified by the
+ * string <code>align</code>. The <code>region</code> parameter must be
+ * one of the strings <code>"NORTH"</code>, <code>"EAST"</code>,
+ * <code>"SOUTH"</code>, or <code>"WEST"</code> and the <code>align</code>
+ * parameter must be <code>"LEFT"</code>, <code>"RIGHT"</code>, or
+ * <code>"CENTER"</code>. By default, side panels use
+ * <code>CENTER</code> alignment.
+ */
+
+ void setRegionAlignment(std::string region, std::string align);
+
+/*
+ * Operator: ==
+ * Usage: if (w1 == w2) ...
+ * ------------------------
+ * Checks whether the two objects refer to the same window.
+ */
+
+ bool operator==(GWindow w2);
+
+/*
+ * Operator: !=
+ * Usage: if (w1 != w2) ...
+ * ------------------------
+ * Checks whether the two objects refer to different windows.
+ */
+
+ bool operator!=(GWindow w2);
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+ explicit GWindow(bool visible);
+ GWindow(double width, double height, bool visible);
+ GWindow(GWindowData *gwd);
+
+private:
+
+/* Instance variables */
+
+ GWindowData *gwd;
+
+/* Private methods */
+
+ void initGWindow(double width, double height, bool visible);
+
+ friend class Platform;
+ friend class GKeyEvent;
+ friend class GMouseEvent;
+ friend class GWindowEvent;
+
+};
+
+/*
+ * Function: repaint
+ * Usage: repaint();
+ * -----------------
+ * Issues a request to update all graphics windows. This function
+ * is called automatically when the program pauses, waits for an
+ * event, waits for user input on the console, or terminates. As
+ * a result, most clients never need to call repaint explicitly.
+ */
+
+void repaint();
+
+/*
+ * Function: pause
+ * Usage: pause(milliseconds);
+ * ---------------------------
+ * Pauses for the indicated number of milliseconds. This function is
+ * useful for animation where the motion would otherwise be too fast.
+ */
+
+void pause(double milliseconds);
+
+/*
+ * Function: getScreenWidth
+ * Usage: width = getScreenWidth();
+ * --------------------------------
+ * Returns the width of the entire display screen.
+ */
+
+double getScreenWidth();
+
+/*
+ * Function: getScreenHeight
+ * Usage: height = getScreenHeight();
+ * ----------------------------------
+ * Returns the height of the entire display screen.
+ */
+
+double getScreenHeight();
+
+/*
+ * Function: convertColorToRGB
+ * Usage: int rgb = convertColorToRGB(colorName);
+ * ----------------------------------------------
+ * Converts a color name into an integer that encodes the
+ * red, green, and blue components of the color.
+ */
+
+int convertColorToRGB(std::string colorName);
+
+/*
+ * Function: convertRGBToColor
+ * Usage: int colorName = convertRGBToColor(rgb);
+ * ----------------------------------------------
+ * Converts an <code>rgb</code> value into a color name in the
+ * form <code>"#rrggbb"</code>. Each of the <code>rr</code>,
+ * <code>gg</code>, and <code>bb</code> values are two-digit
+ * hexadecimal numbers indicating the intensity of that component.
+ */
+
+std::string convertRGBToColor(int rgb);
+
+/*
+ * Function: waitForClick
+ * Usage: waitForClick();
+ * ----------------------
+ * Waits for a mouse click to occur anywhere in any window.
+ */
+
+void waitForClick();
+
+/*
+ * Function: exitGraphics
+ * Usage: exitGraphics();
+ * ----------------------
+ * Closes all graphics windows and exits from the application without
+ * waiting for any additional user interaction.
+ */
+
+void exitGraphics();
+
+#include "console.h"
+#include "private/main.h"
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/hashmap.cpp b/labb8/lib/StanfordCPPLib/hashmap.cpp
new file mode 100755
index 0000000..4dd77d6
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/hashmap.cpp
@@ -0,0 +1,296 @@
+/*
+ * File: hashmap.cpp
+ * -----------------
+ * This file contains the hash functions that are used in conjunction
+ * with the HashMap class.
+ */
+
+#include <iostream>
+#include <string>
+#include "hashmap.h"
+#include "hashset.h"
+#include "lexicon.h"
+#include "queue.h"
+#include "set.h"
+#include "stack.h"
+#include "vector.h"
+using namespace std;
+
+/*
+ * Implementation notes: hashCode
+ * ------------------------------
+ * This function takes a string key and uses it to derive a hash code,
+ * which is a nonnegative integer related to the key by a deterministic
+ * function that distributes keys well across the space of integers.
+ * The general method is called linear congruence, which is also used
+ * in random-number generators. The specific algorithm used here is
+ * called djb2 after the initials of its inventor, Daniel J. Bernstein,
+ * Professor of Mathematics at the University of Illinois at Chicago.
+ */
+
+const int HASH_SEED = 5381; /* Starting point for first cycle */
+const int HASH_MULTIPLIER = 33; /* Multiplier for each cycle */
+const int HASH_MASK = unsigned(-1) >> 1; /* All 1 bits except the sign */
+
+int hashCode(const string & str) {
+ unsigned hash = HASH_SEED;
+ int n = str.length();
+ for (int i = 0; i < n; i++) {
+ hash = HASH_MULTIPLIER * hash + str[i];
+ }
+ return int(hash & HASH_MASK);
+}
+
+int hashCode(int key) {
+ return key & HASH_MASK;
+}
+
+int hashCode(char key) {
+ return key;
+}
+
+int hashCode(long key) {
+ return int(key) & HASH_MASK;
+}
+
+int hashCode(double key) {
+ char* byte = (char*) &key;
+ unsigned hash = HASH_SEED;
+ for (int i = 0; i < (int) sizeof(double); i++) {
+ hash = HASH_MULTIPLIER * hash + (int) *byte++;
+ }
+ return hash & HASH_MASK;
+}
+
+
+// hashCode functions for various collections;
+// added by Marty Stepp to allow compound collections.
+// I'm a bit ashamed to have to rewrite so many prototypes, one for each
+// element type; but I can't get it to compile with a template.
+int hashCode(const HashSet<int>& s) {
+ int code = HASH_SEED;
+ foreach (int n in s) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const HashSet<double>& s) {
+ int code = HASH_SEED;
+ foreach (double n in s) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const HashSet<char>& s) {
+ int code = HASH_SEED;
+ foreach (char n in s) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const HashSet<long>& s) {
+ int code = HASH_SEED;
+ foreach (long n in s) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const HashSet<std::string>& s) {
+ int code = HASH_SEED;
+ foreach (std::string n in s) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Lexicon& l) {
+ int code = HASH_SEED;
+ foreach (std::string n in l) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Queue<int>& q) {
+ int code = HASH_SEED;
+ Queue<int> backup = q;
+ while (!backup.isEmpty()) {
+ code = HASH_MULTIPLIER * code + hashCode(backup.dequeue());
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Queue<double>& q) {
+ int code = HASH_SEED;
+ Queue<double> backup = q;
+ while (!backup.isEmpty()) {
+ code = HASH_MULTIPLIER * code + hashCode(backup.dequeue());
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Queue<char>& q) {
+ int code = HASH_SEED;
+ Queue<char> backup = q;
+ while (!backup.isEmpty()) {
+ code = HASH_MULTIPLIER * code + hashCode(backup.dequeue());
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Queue<long>& q) {
+ int code = HASH_SEED;
+ Queue<long> backup = q;
+ while (!backup.isEmpty()) {
+ code = HASH_MULTIPLIER * code + hashCode(backup.dequeue());
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Queue<std::string>& q) {
+ int code = HASH_SEED;
+ Queue<std::string> backup = q;
+ while (!backup.isEmpty()) {
+ code = HASH_MULTIPLIER * code + hashCode(backup.dequeue());
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Set<int>& s) {
+ int code = HASH_SEED;
+ foreach (int n in s) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Set<double>& s) {
+ int code = HASH_SEED;
+ foreach (double n in s) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Set<char>& s) {
+ int code = HASH_SEED;
+ foreach (char n in s) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Set<long>& s) {
+ int code = HASH_SEED;
+ foreach (long n in s) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Set<std::string>& s) {
+ int code = HASH_SEED;
+ foreach (std::string n in s) {
+ code = HASH_MULTIPLIER * code + hashCode(n);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Stack<int>& s) {
+ int code = HASH_SEED;
+ Stack<int> backup = s;
+ while (!backup.isEmpty()) {
+ code = HASH_MULTIPLIER * code + hashCode(backup.pop());
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Stack<double>& s) {
+ int code = HASH_SEED;
+ Stack<double> backup = s;
+ while (!backup.isEmpty()) {
+ code = HASH_MULTIPLIER * code + hashCode(backup.pop());
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Stack<char>& s) {
+ int code = HASH_SEED;
+ Stack<char> backup = s;
+ while (!backup.isEmpty()) {
+ code = HASH_MULTIPLIER * code + hashCode(backup.pop());
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Stack<long>& s) {
+ int code = HASH_SEED;
+ Stack<long> backup = s;
+ while (!backup.isEmpty()) {
+ code = HASH_MULTIPLIER * code + hashCode(backup.pop());
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Stack<std::string>& s) {
+ int code = HASH_SEED;
+ Stack<std::string> backup = s;
+ while (!backup.isEmpty()) {
+ code = HASH_MULTIPLIER * code + hashCode(backup.pop());
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Vector<int>& v) {
+ int code = HASH_SEED;
+ for (int i = 0, size = v.size(); i < size; i++) {
+ code = HASH_MULTIPLIER * code + hashCode(v[i]);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Vector<double>& v) {
+ int code = HASH_SEED;
+ for (int i = 0, size = v.size(); i < size; i++) {
+ code = HASH_MULTIPLIER * code + hashCode(v[i]);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Vector<char>& v) {
+ int code = HASH_SEED;
+ for (int i = 0, size = v.size(); i < size; i++) {
+ code = HASH_MULTIPLIER * code + hashCode(v[i]);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Vector<long>& v) {
+ int code = HASH_SEED;
+ for (int i = 0, size = v.size(); i < size; i++) {
+ code = HASH_MULTIPLIER * code + hashCode(v[i]);
+ }
+ return int(code & HASH_MASK);
+}
+
+int hashCode(const Vector<std::string>& v) {
+ int code = HASH_SEED;
+ for (int i = 0, size = v.size(); i < size; i++) {
+ code = HASH_MULTIPLIER * code + hashCode(v[i]);
+ }
+ return int(code & HASH_MASK);
+}
+
+//template <typename ValueType>
+//int hashCode(const Vector<ValueType>& v) {
+// int code = 0;
+// for (int i = 0, size = v.size(); i < size; i++) {
+// code = 31 * code + hashCode(v[i]);
+// }
+// return code;
+//}
+
diff --git a/labb8/lib/StanfordCPPLib/hashmap.h b/labb8/lib/StanfordCPPLib/hashmap.h
new file mode 100755
index 0000000..5b76ae0
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/hashmap.h
@@ -0,0 +1,663 @@
+/*
+ * File: hashmap.h
+ * ---------------
+ * This file exports the <code>HashMap</code> class, which stores
+ * a set of <i>key</i>-<i>value</i> pairs.
+ */
+
+#ifndef _hashmap_h
+#define _hashmap_h
+
+#include <cstdlib>
+#include <string>
+#include "foreach.h"
+#include "vector.h"
+
+/*
+ * Function: hashCode
+ * Usage: int hash = hashCode(key);
+ * --------------------------------
+ * Returns a hash code for the specified key, which is always a
+ * nonnegative integer. This function is overloaded to support
+ * all of the primitive types and the C++ <code>string</code> type.
+ */
+
+int hashCode(const std::string & key);
+int hashCode(int key);
+int hashCode(char key);
+int hashCode(long key);
+int hashCode(double key);
+
+/*
+ * Class: HashMap<KeyType,ValueType>
+ * ---------------------------------
+ * This class implements an efficient association between
+ * <b><i>keys</i></b> and <b><i>values</i></b>. This class is
+ * identical to the <a href="Map-class.html"><code>Map</code></a> class
+ * except for the fact that it uses a hash table as its underlying
+ * representation. Although the <code>HashMap</code> class operates in
+ * constant time, the iterator for <code>HashMap</code> returns the
+ * values in a seemingly random order.
+ */
+
+template <typename KeyType, typename ValueType>
+class HashMap {
+
+public:
+
+/*
+ * Constructor: HashMap
+ * Usage: HashMap<KeyType,ValueType> map;
+ * --------------------------------------
+ * Initializes a new empty map that associates keys and values of
+ * the specified types. The type used for the key must define
+ * the <code>==</code> operator, and there must be a free function
+ * with the following signature:
+ *
+ *<pre>
+ * int hashCode(KeyType key);
+ *</pre>
+ *
+ * that returns a positive integer determined by the key. This interface
+ * exports <code>hashCode</code> functions for <code>string</code> and
+ * the C++ primitive types.
+ */
+
+ HashMap();
+
+/*
+ * Destructor: ~HashMap
+ * --------------------
+ * Frees any heap storage associated with this map.
+ */
+
+ virtual ~HashMap();
+
+/*
+ * Method: size
+ * Usage: int nEntries = map.size();
+ * ---------------------------------
+ * Returns the number of entries in this map.
+ */
+
+ int size() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (map.isEmpty()) ...
+ * -----------------------------
+ * Returns <code>true</code> if this map contains no entries.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: put
+ * Usage: map.put(key, value);
+ * ---------------------------
+ * Associates <code>key</code> with <code>value</code> in this map.
+ * Any previous value associated with <code>key</code> is replaced
+ * by the new value.
+ */
+
+ void put(KeyType key, ValueType value);
+
+/*
+ * Method: get
+ * Usage: ValueType value = map.get(key);
+ * --------------------------------------
+ * Returns the value associated with <code>key</code> in this map.
+ * If <code>key</code> is not found, <code>get</code> returns the
+ * default value for <code>ValueType</code>.
+ */
+
+ ValueType get(KeyType key) const;
+
+/*
+ * Method: containsKey
+ * Usage: if (map.containsKey(key)) ...
+ * ------------------------------------
+ * Returns <code>true</code> if there is an entry for <code>key</code>
+ * in this map.
+ */
+
+ bool containsKey(KeyType key) const;
+
+/*
+ * Method: remove
+ * Usage: map.remove(key);
+ * -----------------------
+ * Removes any entry for <code>key</code> from this map.
+ */
+
+ void remove(KeyType key);
+
+/*
+ * Method: clear
+ * Usage: map.clear();
+ * -------------------
+ * Removes all entries from this map.
+ */
+
+ void clear();
+
+/*
+ * Method: keys
+ * Usage: Vector<KeyType> keys = map.keys();
+ * -------------------------------------------
+ * Returns a collection containing all keys in this map.
+ */
+
+ Vector<KeyType> keys() const;
+
+/*
+ * Method: values
+ * Usage: Vector<ValueType> values = map.values();
+ * -------------------------------------------
+ * Returns a collection containing all values in this map.
+ */
+
+ Vector<ValueType> values() const;
+
+/*
+ * Operator: []
+ * Usage: map[key]
+ * ---------------
+ * Selects the value associated with <code>key</code>. This syntax
+ * makes it easy to think of a map as an "associative array"
+ * indexed by the key type. If <code>key</code> is already present
+ * in the map, this function returns a reference to its associated
+ * value. If key is not present in the map, a new entry is created
+ * whose value is set to the default for the value type.
+ */
+
+ ValueType & operator[](KeyType key);
+ ValueType operator[](KeyType key) const;
+
+/*
+ * Method: toString
+ * Usage: string str = map.toString();
+ * -----------------------------------
+ * Converts the map to a printable string representation.
+ */
+
+ std::string toString();
+
+/*
+ * Method: mapAll
+ * Usage: map.mapAll(fn);
+ * ----------------------
+ * Iterates through the map entries and calls <code>fn(key, value)</code>
+ * for each one. The keys are processed in an undetermined order.
+ */
+
+ void mapAll(void (*fn)(KeyType, ValueType)) const;
+ void mapAll(void (*fn)(const KeyType &, const ValueType &)) const;
+ template <typename FunctorType>
+ void mapAll(FunctorType fn) const;
+
+/*
+ * Additional HashMap operations
+ * -----------------------------
+ * In addition to the methods listed in this interface, the HashMap
+ * class supports the following operations:
+ *
+ * - Stream I/O using the << and >> operators
+ * - Deep copying for the copy constructor and assignment operator
+ * - Iteration using the range-based for statement and STL iterators
+ *
+ * The HashMap class makes no guarantees about the order of iteration.
+ */
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+/*
+ * Implementation notes:
+ * ---------------------
+ * The HashMap class is represented using a hash table that uses
+ * bucket chaining to resolve collisions.
+ */
+
+private:
+
+/* Constant definitions */
+
+ static const int INITIAL_BUCKET_COUNT = 101;
+ static const int MAX_LOAD_PERCENTAGE = 70;
+
+/* Type definition for cells in the bucket chain */
+
+ struct Cell {
+ KeyType key;
+ ValueType value;
+ Cell *next;
+ };
+
+/* Instance variables */
+
+ Vector<Cell *> buckets;
+ int nBuckets;
+ int numEntries;
+
+/* Private methods */
+
+/*
+ * Private method: createBuckets
+ * Usage: createBuckets(nBuckets);
+ * -------------------------------
+ * Sets up the vector of buckets to have nBuckets entries, each NULL.
+ * If asked to make empty vector, makes one bucket just to simplify
+ * handling elsewhere.
+ */
+
+ void createBuckets(int nBuckets) {
+ if (nBuckets == 0) nBuckets = 1;
+ buckets = Vector<Cell *>(nBuckets, NULL);
+ this->nBuckets = nBuckets;
+ numEntries = 0;
+ }
+
+/*
+ * Private method: deleteBuckets
+ * Usage: deleteBuckets(buckets);
+ * ------------------------------
+ * Deletes all the cells in the linked lists contained in vector.
+ */
+
+ void deleteBuckets(Vector <Cell *> & buckets) {
+ for (int i = 0; i < buckets.size(); i++) {
+ Cell *cp = buckets[i];
+ while (cp != NULL) {
+ Cell *np = cp->next;
+ delete cp;
+ cp = np;
+ }
+ buckets[i] = NULL;
+ }
+ }
+
+/*
+ * Private method: expandAndRehash
+ * Usage: expandAndRehash();
+ * -------------------------
+ * This method is used to increase the number of buckets in the map
+ * and then rehashes all existing entries and adds them into new buckets.
+ * This operation is used when the load factor (i.e. the number of cells
+ * per bucket) has increased enough to warrant this O(N) operation to
+ * enlarge and redistribute the entries.
+ */
+
+ void expandAndRehash() {
+ Vector<Cell *>oldBuckets = buckets;
+ createBuckets(oldBuckets.size() * 2 + 1);
+ for (int i = 0; i < oldBuckets.size(); i++) {
+ for (Cell *cp = oldBuckets[i]; cp != NULL; cp = cp->next) {
+ put(cp->key, cp->value);
+ }
+ }
+ deleteBuckets(oldBuckets);
+ }
+
+/*
+ * Private method: findCell
+ * Usage: Cell *cp = findCell(bucket, key);
+ * Cell *cp = findCell(bucket, key, parent);
+ * ------------------------------------------------
+ * Finds a cell in the chain for the specified bucket that matches key.
+ * If a match is found, the return value is a pointer to the cell containing
+ * the matching key. If no match is found, the function returns NULL.
+ * If the optional third argument is supplied, it is filled in with the
+ * cell preceding the matching cell to allow the client to splice out
+ * the target cell in the delete call. If parent is NULL, it indicates
+ * that the cell is the first cell in the bucket chain.
+ */
+
+ Cell *findCell(int bucket, KeyType key) const {
+ Cell *dummy;
+ return findCell(bucket, key, dummy);
+ }
+
+ Cell *findCell(int bucket, KeyType key, Cell * & parent) const {
+ parent = NULL;
+ Cell *cp = buckets.get(bucket);
+ while (cp != NULL && key != cp->key) {
+ parent = cp;
+ cp = cp->next;
+ }
+ return cp;
+ }
+
+ void deepCopy(const HashMap & src) {
+ createBuckets(src.nBuckets);
+ for (int i = 0; i < src.nBuckets; i++) {
+ for (Cell *cp = src.buckets.get(i); cp != NULL; cp = cp->next) {
+ put(cp->key, cp->value);
+ }
+ }
+ }
+
+public:
+
+/*
+ * Hidden features
+ * ---------------
+ * The remainder of this file consists of the code required to
+ * support deep copying and iteration. Including these methods
+ * in the public interface would make that interface more
+ * difficult to understand for the average client.
+ */
+
+/*
+ * Deep copying support
+ * --------------------
+ * This copy constructor and operator= are defined to make a
+ * deep copy, making it possible to pass/return maps by value
+ * and assign from one map to another.
+ */
+
+ HashMap & operator=(const HashMap & src) {
+ if (this != &src) {
+ clear();
+ deepCopy(src);
+ }
+ return *this;
+ }
+
+ HashMap(const HashMap & src) {
+ deepCopy(src);
+ }
+
+/*
+ * Iterator support
+ * ----------------
+ * The classes in the StanfordCPPLib collection implement input
+ * iterators so that they work symmetrically with respect to the
+ * corresponding STL classes.
+ */
+
+ class iterator : public std::iterator<std::input_iterator_tag,KeyType> {
+
+ private:
+
+ const HashMap *mp; /* Pointer to the map */
+ int bucket; /* Index of current bucket */
+ Cell *cp; /* Current cell in bucket chain */
+
+ public:
+
+ iterator() {
+ /* Empty */
+ }
+
+ iterator(const HashMap *mp, bool end) {
+ this->mp = mp;
+ if (end) {
+ bucket = mp->nBuckets;
+ cp = NULL;
+ } else {
+ bucket = 0;
+ cp = mp->buckets.get(bucket);
+ while (cp == NULL && ++bucket < mp->nBuckets) {
+ cp = mp->buckets.get(bucket);
+ }
+ }
+ }
+
+ iterator(const iterator & it) {
+ mp = it.mp;
+ bucket = it.bucket;
+ cp = it.cp;
+ }
+
+ iterator & operator++() {
+ cp = cp->next;
+ while (cp == NULL && ++bucket < mp->nBuckets) {
+ cp = mp->buckets.get(bucket);
+ }
+ return *this;
+ }
+
+ iterator operator++(int) {
+ iterator copy(*this);
+ operator++();
+ return copy;
+ }
+
+ bool operator==(const iterator & rhs) {
+ return mp == rhs.mp && bucket == rhs.bucket && cp == rhs.cp;
+ }
+
+ bool operator!=(const iterator & rhs) {
+ return !(*this == rhs);
+ }
+
+ KeyType operator*() {
+ return cp->key;
+ }
+
+ KeyType *operator->() {
+ return &cp->key;
+ }
+
+ friend class HashMap;
+
+ };
+
+ iterator begin() const {
+ return iterator(this, false);
+ }
+
+ iterator end() const {
+ return iterator(this, true);
+ }
+
+};
+
+/*
+ * Implementation notes: HashMap class
+ * -----------------------------------
+ * In this map implementation, the entries are stored in a hashtable.
+ * The hashtable keeps a vector of "buckets", where each bucket is a
+ * linked list of elements that share the same hash code (i.e. hash
+ * collisions are resolved by chaining). The buckets are dynamically
+ * allocated so that we can change the the number of buckets (rehash)
+ * when the load factor becomes too high. The map should provide O(1)
+ * performance on the put/remove/get operations.
+ */
+
+template <typename KeyType,typename ValueType>
+HashMap<KeyType,ValueType>::HashMap() {
+ createBuckets(INITIAL_BUCKET_COUNT);
+}
+
+template <typename KeyType,typename ValueType>
+HashMap<KeyType,ValueType>::~HashMap() {
+ deleteBuckets(buckets);
+}
+
+template <typename KeyType,typename ValueType>
+int HashMap<KeyType,ValueType>::size() const {
+ return numEntries;
+}
+
+template <typename KeyType,typename ValueType>
+bool HashMap<KeyType,ValueType>::isEmpty() const {
+ return size() == 0;
+}
+
+template <typename KeyType,typename ValueType>
+void HashMap<KeyType,ValueType>::put(KeyType key, ValueType value) {
+ (*this)[key] = value;
+}
+
+template <typename KeyType,typename ValueType>
+ValueType HashMap<KeyType,ValueType>::get(KeyType key) const {
+ Cell *cp = findCell(hashCode(key) % nBuckets, key);
+ if (cp == NULL) return ValueType();
+ return cp->value;
+}
+
+template <typename KeyType,typename ValueType>
+bool HashMap<KeyType,ValueType>::containsKey(KeyType key) const {
+ return findCell(hashCode(key) % nBuckets, key) != NULL;
+}
+
+template <typename KeyType,typename ValueType>
+void HashMap<KeyType,ValueType>::remove(KeyType key) {
+ int bucket = hashCode(key) % nBuckets;
+ Cell *parent;
+ Cell *cp = findCell(bucket, key, parent);
+ if (cp != NULL) {
+ if (parent == NULL) {
+ buckets[bucket] = cp->next;
+ } else {
+ parent->next = cp->next;
+ }
+ delete cp;
+ numEntries--;
+ }
+}
+
+template <typename KeyType,typename ValueType>
+void HashMap<KeyType,ValueType>::clear() {
+ deleteBuckets(buckets);
+ numEntries = 0;
+}
+
+template <typename KeyType,typename ValueType>
+Vector<KeyType> HashMap<KeyType,ValueType>::keys() const {
+ Vector<KeyType> keyset;
+ foreach (KeyType key in *this) {
+ keyset.add(key);
+ }
+ return keyset;
+}
+
+template <typename KeyType,typename ValueType>
+Vector<ValueType> HashMap<KeyType,ValueType>::values() const {
+ Vector<ValueType> values;
+ foreach (KeyType key in *this) {
+ values.add(this->get(key));
+ }
+ return values;
+}
+
+template <typename KeyType,typename ValueType>
+ValueType & HashMap<KeyType,ValueType>::operator[](KeyType key) {
+ int bucket = hashCode(key) % nBuckets;
+ Cell *cp = findCell(bucket, key);
+ if (cp == NULL) {
+ if (numEntries > MAX_LOAD_PERCENTAGE * nBuckets / 100.0) {
+ expandAndRehash();
+ bucket = hashCode(key) % nBuckets;
+ }
+ cp = new Cell;
+ cp->key = key;
+ cp->value = ValueType();
+ cp->next = buckets[bucket];
+ buckets[bucket] = cp;
+ numEntries++;
+ }
+ return cp->value;
+}
+
+template <typename KeyType,typename ValueType>
+void HashMap<KeyType,ValueType>::mapAll(void (*fn)(KeyType, ValueType)) const {
+ for (int i = 0 ; i < buckets.size(); i++) {
+ for (Cell *cp = buckets.get(i); cp != NULL; cp = cp->next) {
+ fn(cp->key, cp->value);
+ }
+ }
+}
+
+template <typename KeyType,typename ValueType>
+void HashMap<KeyType,ValueType>::mapAll(void (*fn)(const KeyType &,
+ const ValueType &)) const {
+ for (int i = 0 ; i < buckets.size(); i++) {
+ for (Cell *cp = buckets.get(i); cp != NULL; cp = cp->next) {
+ fn(cp->key, cp->value);
+ }
+ }
+}
+
+template <typename KeyType,typename ValueType>
+template <typename FunctorType>
+void HashMap<KeyType,ValueType>::mapAll(FunctorType fn) const {
+ for (int i = 0 ; i < buckets.size(); i++) {
+ for (Cell *cp = buckets.get(i); cp != NULL; cp = cp->next) {
+ fn(cp->key, cp->value);
+ }
+ }
+}
+
+template <typename KeyType, typename ValueType>
+ValueType HashMap<KeyType,ValueType>::operator[](KeyType key) const {
+ return get(key);
+}
+
+template <typename KeyType, typename ValueType>
+std::string HashMap<KeyType,ValueType>::toString() {
+ ostringstream os;
+ os << *this;
+ return os.str();
+}
+
+/*
+ * Implementation notes: << and >>
+ * -------------------------------
+ * The insertion and extraction operators use the template facilities in
+ * strlib.h to read and write generic values in a way that treats strings
+ * specially.
+ */
+
+template <typename KeyType, typename ValueType>
+std::ostream & operator<<(std::ostream & os,
+ const HashMap<KeyType,ValueType> & map) {
+ os << "{";
+ typename HashMap<KeyType,ValueType>::iterator begin = map.begin();
+ typename HashMap<KeyType,ValueType>::iterator end = map.end();
+ typename HashMap<KeyType,ValueType>::iterator it = begin;
+ while (it != end) {
+ if (it != begin) os << ", ";
+ writeGenericValue(os, *it, false);
+ os << ":";
+ writeGenericValue(os, map[*it], false);
+ ++it;
+ }
+ return os << "}";
+}
+
+template <typename KeyType, typename ValueType>
+std::istream & operator>>(std::istream & is,
+ HashMap<KeyType,ValueType> & map) {
+ char ch;
+ is >> ch;
+ if (ch != '{') error("operator >>: Missing {");
+ map.clear();
+ is >> ch;
+ if (ch != '}') {
+ is.unget();
+ while (true) {
+ KeyType key;
+ readGenericValue(is, key);
+ is >> ch;
+ if (ch != ':') error("operator >>: Missing colon after key");
+ ValueType value;
+ readGenericValue(is, value);
+ map[key] = value;
+ is >> ch;
+ if (ch == '}') break;
+ if (ch != ',') {
+ error(std::string("operator >>: Unexpected character ") + ch);
+ }
+ }
+ }
+ return is;
+}
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/hashset.h b/labb8/lib/StanfordCPPLib/hashset.h
new file mode 100755
index 0000000..f7551c5
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/hashset.h
@@ -0,0 +1,613 @@
+/*
+ * File: hashset.h
+ * ---------------
+ * This file exports the <code>HashSet</code> class, which
+ * implements an efficient abstraction for storing sets of values.
+ */
+
+#ifndef _hashset_h
+#define _hashset_h
+
+#include <iostream>
+#include "foreach.h"
+#include "hashmap.h"
+#include "vector.h"
+
+/*
+ * Class: HashSet<ValueType>
+ * -------------------------
+ * This class implements an efficient abstraction for storing sets
+ * of distinct elements. This class is identical to the <code>Set</code>
+ * class except for the fact that it uses a hash table as its underlying
+ * representation. The advantage of the <code>HashSet</code> class is that
+ * it operates in constant time, as opposed to the <i>O</i>(log <i>N</i>)
+ * time for the <code>Set</code> class. The disadvantage of
+ * <code>HashSet</code> is that iterators return the values in a
+ * seemingly random order.
+ */
+
+template <typename ValueType>
+class HashSet {
+
+public:
+
+/*
+ * Constructor: HashSet
+ * Usage: HashSet<ValueType> set;
+ * ------------------------------
+ * Initializes an empty set of the specified element type.
+ */
+
+ HashSet();
+
+/*
+ * Destructor: ~HashSet
+ * --------------------
+ * Frees any heap storage associated with this set.
+ */
+
+ virtual ~HashSet();
+
+/*
+ * Method: size
+ * Usage: count = set.size();
+ * --------------------------
+ * Returns the number of elements in this set.
+ */
+
+ int size() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (set.isEmpty()) ...
+ * -----------------------------
+ * Returns <code>true</code> if this set contains no elements.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: add
+ * Usage: set.add(value);
+ * ----------------------
+ * Adds an element to this set, if it was not already there. For
+ * compatibility with the STL <code>set</code> class, this method
+ * is also exported as <code>insert</code>.
+ */
+
+ void add(const ValueType & value);
+ void insert(const ValueType & value);
+
+/*
+ * Method: remove
+ * Usage: set.remove(value);
+ * -------------------------
+ * Removes an element from this set. If the value was not
+ * contained in the set, no error is generated and the set
+ * remains unchanged.
+ */
+
+ void remove(const ValueType & value);
+
+/*
+ * Method: contains
+ * Usage: if (set.contains(value)) ...
+ * -----------------------------------
+ * Returns <code>true</code> if the specified value is in this set.
+ */
+
+ bool contains(const ValueType & value) const;
+
+/*
+ * Method: isSubsetOf
+ * Usage: if (set.isSubsetOf(set2)) ...
+ * ------------------------------------
+ * Implements the subset relation on sets. It returns
+ * <code>true</code> if every element of this set is
+ * contained in <code>set2</code>.
+ */
+
+ bool isSubsetOf(const HashSet & set2) const;
+
+/*
+ * Method: clear
+ * Usage: set.clear();
+ * -------------------
+ * Removes all elements from this set.
+ */
+
+ void clear();
+
+/*
+ * Operator: ==
+ * Usage: set1 == set2
+ * -------------------
+ * Returns <code>true</code> if <code>set1</code> and <code>set2</code>
+ * contain the same elements.
+ */
+
+ bool operator==(const HashSet & set2) const;
+
+/*
+ * Operator: !=
+ * Usage: set1 != set2
+ * -------------------
+ * Returns <code>true</code> if <code>set1</code> and <code>set2</code>
+ * are different.
+ */
+
+ bool operator!=(const HashSet & set2) const;
+
+/*
+ * Operator: +
+ * Usage: set1 + set2
+ * set1 + element
+ * ---------------------
+ * Returns the union of sets <code>set1</code> and <code>set2</code>, which
+ * is the set of elements that appear in at least one of the two sets. The
+ * right hand set can be replaced by an element of the value type, in which
+ * case the operator returns a new set formed by adding that element.
+ */
+
+ HashSet operator+(const HashSet & set2) const;
+ HashSet operator+(const ValueType & element) const;
+
+/*
+ * Operator: *
+ * Usage: set1 * set2
+ * ------------------
+ * Returns the intersection of sets <code>set1</code> and <code>set2</code>,
+ * which is the set of all elements that appear in both.
+ */
+
+ HashSet operator*(const HashSet & set2) const;
+
+/*
+ * Operator: -
+ * Usage: set1 - set2
+ * set1 - element
+ * ---------------------
+ * Returns the difference of sets <code>set1</code> and <code>set2</code>,
+ * which is all of the elements that appear in <code>set1</code> but
+ * not <code>set2</code>. The right hand set can be replaced by an
+ * element of the value type, in which case the operator returns a new
+ * set formed by removing that element.
+ */
+
+ HashSet operator-(const HashSet & set2) const;
+ HashSet operator-(const ValueType & element) const;
+
+/*
+ * Operator: +=
+ * Usage: set1 += set2;
+ * set1 += value;
+ * ---------------------
+ * Adds all of the elements from <code>set2</code> (or the single
+ * specified value) to <code>set1</code>. As a convenience, the
+ * <code>HashSet</code> package also overloads the comma operator so
+ * that it is possible to initialize a set like this:
+ *
+ *<pre>
+ * HashSet&lt;int&lt; digits;
+ * digits += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
+ *</pre>
+ */
+
+ HashSet & operator+=(const HashSet & set2);
+ HashSet & operator+=(const ValueType & value);
+
+/*
+ * Operator: *=
+ * Usage: set1 *= set2;
+ * --------------------
+ * Removes any elements from <code>set1</code> that are not present in
+ * <code>set2</code>.
+ */
+
+ HashSet & operator*=(const HashSet & set2);
+
+/*
+ * Operator: -=
+ * Usage: set1 -= set2;
+ * set1 -= value;
+ * ---------------------
+ * Removes the elements from <code>set2</code> (or the single
+ * specified value) from <code>set1</code>. As a convenience, the
+ * <code>HashSet</code> package also overloads the comma operator so
+ * that it is possible to remove multiple elements from a set
+ * like this:
+ *
+ *<pre>
+ * digits -= 0, 2, 4, 6, 8;
+ *</pre>
+ *
+ * which removes the values 0, 2, 4, 6, and 8 from the set
+ * <code>digits</code>.
+ */
+
+ HashSet & operator-=(const HashSet & set2);
+ HashSet & operator-=(const ValueType & value);
+
+/*
+ * Method: first
+ * Usage: ValueType value = set.first();
+ * -------------------------------------
+ * Returns the first value in the set in the order established by the
+ * <code>foreach</code> macro. If the set is empty, <code>first</code>
+ * generates an error.
+ */
+
+ ValueType first() const;
+
+/*
+ * Method: toString
+ * Usage: string str = set.toString();
+ * -----------------------------------
+ * Converts the set to a printable string representation.
+ */
+
+ std::string toString();
+
+/*
+ * Method: mapAll
+ * Usage: set.mapAll(fn);
+ * ----------------------
+ * Iterates through the elements of the set and calls <code>fn(value)</code>
+ * for each one. The values are processed in ascending order, as defined
+ * by the comparison function.
+ */
+
+ void mapAll(void (*fn)(ValueType)) const;
+ void mapAll(void (*fn)(const ValueType &)) const;
+
+ template <typename FunctorType>
+ void mapAll(FunctorType fn) const;
+
+/*
+ * Additional HashSet operations
+ * -----------------------------
+ * In addition to the methods listed in this interface, the HashSet
+ * class supports the following operations:
+ *
+ * - Stream I/O using the << and >> operators
+ * - Deep copying for the copy constructor and assignment operator
+ * - Iteration using the range-based for statement and STL iterators
+ *
+ * The iteration forms process the HashSet in an unspecified order.
+ */
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+private:
+
+ HashMap<ValueType,bool> map; /* Map used to store the element */
+ bool removeFlag; /* Flag to differentiate += and -= */
+
+public:
+
+/*
+ * Hidden features
+ * ---------------
+ * The remainder of this file consists of the code required to
+ * support the comma operator, deep copying, and iteration.
+ * Including these methods in the public interface would make
+ * that interface more difficult to understand for the average client.
+ */
+
+ HashSet & operator,(const ValueType & value) {
+ if (this->removeFlag) {
+ this->remove(value);
+ } else {
+ this->add(value);
+ }
+ return *this;
+ }
+
+/*
+ * Iterator support
+ * ----------------
+ * The classes in the StanfordCPPLib collection implement input
+ * iterators so that they work symmetrically with respect to the
+ * corresponding STL classes.
+ */
+
+ class iterator : public std::iterator<std::input_iterator_tag,ValueType> {
+
+ private:
+
+ typename HashMap<ValueType,bool>::iterator mapit;
+
+ public:
+
+ iterator() {
+ /* Empty */
+ }
+
+ iterator(typename HashMap<ValueType,bool>::iterator it) : mapit(it) {
+ /* Empty */
+ }
+
+ iterator(const iterator & it) {
+ mapit = it.mapit;
+ }
+
+ iterator & operator++() {
+ ++mapit;
+ return *this;
+ }
+
+ iterator operator++(int) {
+ iterator copy(*this);
+ operator++();
+ return copy;
+ }
+
+ bool operator==(const iterator & rhs) {
+ return mapit == rhs.mapit;
+ }
+
+ bool operator!=(const iterator & rhs) {
+ return !(*this == rhs);
+ }
+
+ ValueType operator*() {
+ return *mapit;
+ }
+
+ ValueType *operator->() {
+ return mapit;
+ }
+ };
+
+ iterator begin() const {
+ return iterator(map.begin());
+ }
+
+ iterator end() const {
+ return iterator(map.end());
+ }
+
+};
+
+extern void error(std::string msg);
+
+template <typename ValueType>
+HashSet<ValueType>::HashSet() {
+ /* Empty */
+}
+
+template <typename ValueType>
+HashSet<ValueType>::~HashSet() {
+ /* Empty */
+}
+
+template <typename ValueType>
+int HashSet<ValueType>::size() const {
+ return map.size();
+}
+
+template <typename ValueType>
+bool HashSet<ValueType>::isEmpty() const {
+ return map.isEmpty();
+}
+
+template <typename ValueType>
+void HashSet<ValueType>::add(const ValueType & value) {
+ map.put(value, true);
+}
+
+template <typename ValueType>
+void HashSet<ValueType>::insert(const ValueType & value) {
+ map.put(value, true);
+}
+
+template <typename ValueType>
+void HashSet<ValueType>::remove(const ValueType & value) {
+ map.remove(value);
+}
+
+template <typename ValueType>
+bool HashSet<ValueType>::contains(const ValueType & value) const {
+ return map.containsKey(value);
+}
+
+template <typename ValueType>
+void HashSet<ValueType>::clear() {
+ map.clear();
+}
+
+template <typename ValueType>
+bool HashSet<ValueType>::isSubsetOf(const HashSet & set2) const {
+ iterator it = begin();
+ iterator end = this->end();
+ while (it != end) {
+ if (!set2.map.containsKey(*it)) return false;
+ ++it;
+ }
+ return true;
+}
+
+/*
+ * Implementation notes: set operators
+ * -----------------------------------
+ * The implementations for the set operators use iteration to walk
+ * over the elements in one or both sets.
+ */
+
+template <typename ValueType>
+bool HashSet<ValueType>::operator==(const HashSet & set2) const {
+ return this->isSubsetOf(set2) && set2.isSubsetOf(*this);
+}
+
+template <typename ValueType>
+bool HashSet<ValueType>::operator!=(const HashSet & set2) const {
+ return !(*this == set2);
+}
+
+template <typename ValueType>
+HashSet<ValueType> HashSet<ValueType>::operator+(const HashSet & set2) const {
+ HashSet<ValueType> set = *this;
+ foreach (ValueType value in set2) {
+ set.add(value);
+ }
+ return set;
+}
+
+template <typename ValueType>
+HashSet<ValueType>
+HashSet<ValueType>::operator+(const ValueType & element) const {
+ HashSet<ValueType> set = *this;
+ set.add(element);
+ return set;
+}
+
+template <typename ValueType>
+HashSet<ValueType> HashSet<ValueType>::operator*(const HashSet & set2) const {
+ HashSet<ValueType> set;
+ foreach (ValueType value in *this) {
+ if (set2.map.containsKey(value)) set.add(value);
+ }
+ return set;
+}
+
+template <typename ValueType>
+HashSet<ValueType> HashSet<ValueType>::operator-(const HashSet & set2) const {
+ HashSet<ValueType> set;
+ foreach (ValueType value in *this) {
+ if (!set2.map.containsKey(value)) set.add(value);
+ }
+ return set;
+}
+
+template <typename ValueType>
+HashSet<ValueType>
+HashSet<ValueType>::operator-(const ValueType & element) const {
+ HashSet<ValueType> set = *this;
+ set.remove(element);
+ return set;
+}
+
+template <typename ValueType>
+HashSet<ValueType> & HashSet<ValueType>::operator+=(const HashSet & set2) {
+ foreach (ValueType value in set2) {
+ this->add(value);
+ }
+ return *this;
+}
+
+template <typename ValueType>
+HashSet<ValueType> & HashSet<ValueType>::operator+=(const ValueType & value) {
+ this->add(value);
+ this->removeFlag = false;
+ return *this;
+}
+
+template <typename ValueType>
+HashSet<ValueType> & HashSet<ValueType>::operator*=(const HashSet & set2) {
+ Vector<ValueType> toRemove;
+ foreach (ValueType value in *this) {
+ if (!set2.map.containsKey(value)) toRemove.add(value);
+ }
+ foreach (ValueType value in toRemove) {
+ this->remove(value);
+ }
+ return *this;
+}
+
+template <typename ValueType>
+HashSet<ValueType> & HashSet<ValueType>::operator-=(const HashSet & set2) {
+ Vector<ValueType> toRemove;
+ foreach (ValueType value in *this) {
+ if (set2.map.containsKey(value)) toRemove.add(value);
+ }
+ foreach (ValueType value in toRemove) {
+ this->remove(value);
+ }
+ return *this;
+}
+
+template <typename ValueType>
+HashSet<ValueType> & HashSet<ValueType>::operator-=(const ValueType & value) {
+ this->remove(value);
+ this->removeFlag = true;
+ return *this;
+}
+
+template <typename ValueType>
+ValueType HashSet<ValueType>::first() const {
+ if (isEmpty()) error("first: set is empty");
+ return *begin();
+}
+
+template <typename ValueType>
+std::string HashSet<ValueType>::toString() {
+ ostringstream os;
+ os << *this;
+ return os.str();
+}
+
+template <typename ValueType>
+void HashSet<ValueType>::mapAll(void (*fn)(ValueType)) const {
+ map.mapAll(fn);
+}
+
+template <typename ValueType>
+void HashSet<ValueType>::mapAll(void (*fn)(const ValueType &)) const {
+ map.mapAll(fn);
+}
+
+template <typename ValueType>
+template <typename FunctorType>
+void HashSet<ValueType>::mapAll(FunctorType fn) const {
+ map.mapAll(fn);
+}
+
+template <typename ValueType>
+std::ostream & operator<<(std::ostream & os, const HashSet<ValueType> & set) {
+ os << "{";
+ bool started = false;
+ foreach (ValueType value in set) {
+ if (started) os << ", ";
+ writeGenericValue(os, value, true);
+ started = true;
+ }
+ os << "}";
+ return os;
+}
+
+template <typename ValueType>
+std::istream & operator>>(std::istream & is, HashSet<ValueType> & set) {
+ char ch;
+ is >> ch;
+ if (ch != '{') error("operator >>: Missing {");
+ set.clear();
+ is >> ch;
+ if (ch != '}') {
+ is.unget();
+ while (true) {
+ ValueType value;
+ readGenericValue(is, value);
+ set += value;
+ is >> ch;
+ if (ch == '}') break;
+ if (ch != ',') {
+ error(std::string("operator >>: Unexpected character ") + ch);
+ }
+ }
+ }
+ return is;
+}
+
+// hashing functions for hash sets; defined in hashmap.cpp
+int hashCode(const HashSet<std::string>& s);
+int hashCode(const HashSet<int>& s);
+int hashCode(const HashSet<char>& s);
+int hashCode(const HashSet<long>& s);
+int hashCode(const HashSet<double>& s);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/lexicon.cpp b/labb8/lib/StanfordCPPLib/lexicon.cpp
new file mode 100755
index 0000000..140bef2
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/lexicon.cpp
@@ -0,0 +1,316 @@
+/*
+ * File: lexicon.cpp
+ * -----------------
+ * A lexicon is a word list. This lexicon is backed by two separate data
+ * structures for storing the words in the list:
+ *
+ * 1) a DAWG (directed acyclic word graph)
+ * 2) a Set<string> of other words.
+ *
+ * Typically the DAWG is used for a large list read from a file in binary
+ * format. The STL set is for words added piecemeal at runtime.
+ *
+ * The DAWG idea comes from an article by Appel & Jacobson, CACM May 1988.
+ * This lexicon implementation only has the code to load/search the DAWG.
+ * The DAWG builder code is quite a bit more intricate, see me (Julie)
+ * if you need it.
+ */
+
+#include <fstream>
+#include <string>
+#include <cstring>
+#include <algorithm>
+#include <cstdlib>
+#include <iostream>
+#include <stdint.h>
+#include "error.h"
+#include "lexicon.h"
+#include "strlib.h"
+using namespace std;
+
+static void toLowerCaseInPlace(string & str);
+
+/*
+ * The DAWG is stored as an array of edges. Each edge is represented by
+ * one 32-bit struct. The 5 "letter" bits indicate the character on this
+ * transition (expressed as integer from 1 to 26), the "accept" bit indicates
+ * if you accept after appending that char (current path forms word), and the
+ * "lastEdge" bit marks this as the last edge in a sequence of childeren.
+ * The bulk of the bits (24) are used for the index within the edge array for
+ * the children of this node. The children are laid out contiguously in
+ * alphabetical order. Since we read edges as binary bits from a file in
+ * a big-endian format, we have to swap the struct order for little-endian
+ * machines.
+ */
+
+Lexicon::Lexicon() {
+ edges = start = NULL;
+ numEdges = numDawgWords = 0;
+}
+
+Lexicon::Lexicon(string filename) {
+ edges = start = NULL;
+ numEdges = numDawgWords = 0;
+ addWordsFromFile(filename);
+}
+
+Lexicon::~Lexicon() {
+ if (edges) delete[] edges;
+}
+
+/*
+ * Swaps a 4-byte long from big to little endian byte order
+ */
+
+static uint32_t my_ntohl(uint32_t arg) {
+ uint32_t result = ((arg & 0xff000000) >> 24) |
+ ((arg & 0x00ff0000) >> 8) |
+ ((arg & 0x0000ff00) << 8) |
+ ((arg & 0x000000ff) << 24);
+ return result;
+}
+
+/*
+ * Implementation notes: readBinaryFile
+ * ------------------------------------
+ * The binary lexicon file format must follow this pattern:
+ * DAWG:<startnode index>:<num bytes>:<num bytes block of edge data>
+ */
+
+void Lexicon::readBinaryFile(string filename) {
+ long startIndex, numBytes;
+ char firstFour[4], expected[] = "DAWG";
+ ifstream istr(filename.c_str(), IOS_IN | IOS_BINARY);
+ if (false) my_ntohl(0);
+ if (istr.fail()) {
+ error("Couldn't open lexicon file " + filename);
+ }
+ istr.read(firstFour, 4);
+ istr.get();
+ istr >> startIndex;
+ istr.get();
+ istr >> numBytes;
+ istr.get();
+ if (istr.fail() || strncmp(firstFour, expected, 4) != 0
+ || startIndex < 0 || numBytes < 0) {
+ error("Improperly formed lexicon file " + filename);
+ }
+ numEdges = numBytes/sizeof(Edge);
+ edges = new Edge[numEdges];
+ start = &edges[startIndex];
+ istr.read((char *)edges, numBytes);
+ if (istr.fail() && !istr.eof()) {
+ error("Improperly formed lexicon file " + filename);
+ }
+
+#if defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
+ uint32_t *cur = (uint32_t *) edges;
+ for (int i = 0; i < numEdges; i++, cur++) {
+ *cur = my_ntohl(*cur);
+ }
+#endif
+
+ istr.close();
+ numDawgWords = countDawgWords(start);
+}
+
+int Lexicon::countDawgWords(Edge *ep) const {
+ int count = 0;
+ while (true) {
+ if (ep->accept) count++;
+ if (ep->children != 0) {
+ count += countDawgWords(&edges[ep->children]);
+ }
+ if (ep->lastEdge) break;
+ ep++;
+ }
+ return count;
+}
+
+/*
+ * Check for DAWG in first 4 to identify as special binary format,
+ * otherwise assume ASCII, one word per line
+ */
+
+void Lexicon::addWordsFromFile(string filename) {
+ char firstFour[4], expected[] = "DAWG";
+ ifstream istr(filename.c_str());
+ if (istr.fail()) {
+ error("Couldn't open lexicon file " + filename);
+ }
+ istr.read(firstFour, 4);
+ if (strncmp(firstFour, expected, 4) == 0) {
+ if (otherWords.size() != 0) {
+ error("Binary files require an empty lexicon");
+ }
+ readBinaryFile(filename);
+ return;
+ }
+ istr.seekg(0);
+ string line;
+ while (getline(istr, line)) {
+ add(line);
+ }
+ istr.close();
+}
+
+int Lexicon::size() const {
+ return numDawgWords + otherWords.size();
+}
+
+bool Lexicon::isEmpty() const {
+ return size() == 0;
+}
+
+void Lexicon::clear() {
+ if (edges) delete[] edges;
+ edges = start = NULL;
+ numEdges = numDawgWords = 0;
+ otherWords.clear();
+}
+
+/*
+ * Implementation notes: findEdgeForChar
+ * -------------------------------------
+ * Iterate over sequence of children to find one that
+ * matches the given char. Returns NULL if we get to
+ * last child without finding a match (thus no such
+ * child edge exists).
+ */
+
+Lexicon::Edge *Lexicon::findEdgeForChar(Edge *children, char ch) const {
+ Edge *curEdge = children;
+ while (true) {
+ if (curEdge->letter == charToOrd(ch)) return curEdge;
+ if (curEdge->lastEdge) return NULL;
+ curEdge++;
+ }
+}
+
+/*
+ * Implementation notes: traceToLastEdge
+ * -------------------------------------
+ * Given a string, trace out path through the DAWG edge-by-edge.
+ * If a path exists, return last edge; otherwise return NULL.
+ */
+
+Lexicon::Edge *Lexicon::traceToLastEdge(const string & s) const {
+ if (!start) return NULL;
+ Edge *curEdge = findEdgeForChar(start, s[0]);
+ int len = (int) s.length();
+ for (int i = 1; i < len; i++) {
+ if (!curEdge || !curEdge->children) return NULL;
+ curEdge = findEdgeForChar(&edges[curEdge->children], s[i]);
+ }
+ return curEdge;
+}
+
+bool Lexicon::containsPrefix(string prefix) const {
+ if (prefix.empty()) return true;
+ toLowerCaseInPlace(prefix);
+ if (traceToLastEdge(prefix)) return true;
+ foreach (string word in otherWords) {
+ if (startsWith(word, prefix)) return true;
+ if (prefix < word) return false;
+ }
+ return false;
+}
+
+bool Lexicon::contains(string word) const {
+ toLowerCaseInPlace(word);
+ Edge *lastEdge = traceToLastEdge(word);
+ if (lastEdge && lastEdge->accept) return true;
+ return otherWords.contains(word);
+}
+
+void Lexicon::add(string word) {
+ toLowerCaseInPlace(word);
+ if (!contains(word)) {
+ otherWords.add(word);
+ }
+}
+
+Lexicon::Lexicon(const Lexicon & src) {
+ deepCopy(src);
+}
+
+Lexicon & Lexicon::operator=(const Lexicon & src) {
+ if (this != &src) {
+ if (edges != NULL) delete[] edges;
+ deepCopy(src);
+ }
+ return *this;
+}
+
+void Lexicon::deepCopy(const Lexicon & src) {
+ if (src.edges == NULL) {
+ edges = NULL;
+ start = NULL;
+ } else {
+ numEdges = src.numEdges;
+ edges = new Edge[src.numEdges];
+ memcpy(edges, src.edges, sizeof(Edge)*src.numEdges);
+ start = edges + (src.start - src.edges);
+ }
+ numDawgWords = src.numDawgWords;
+ otherWords = src.otherWords;
+}
+
+void Lexicon::mapAll(void (*fn)(string)) const {
+ foreach (string word in *this) {
+ fn(word);
+ }
+}
+
+void Lexicon::mapAll(void (*fn)(const string &)) const {
+ foreach (string word in *this) {
+ fn(word);
+ }
+}
+
+void Lexicon::iterator::advanceToNextWordInSet() {
+ if (setIterator == setEnd) {
+ currentSetWord = "";
+ } else {
+ currentSetWord = *setIterator;
+ ++setIterator;
+ }
+}
+
+void Lexicon::iterator::advanceToNextWordInDawg() {
+ if (edgePtr == NULL) {
+ edgePtr = lp->start;
+ } else {
+ advanceToNextEdge();
+ }
+ while (edgePtr != NULL && !edgePtr->accept) {
+ advanceToNextEdge();
+ }
+}
+
+void Lexicon::iterator::advanceToNextEdge() {
+ Edge *ep = edgePtr;
+ if (ep->children == 0) {
+ while (ep != NULL && ep->lastEdge) {
+ if (stack.isEmpty()) {
+ edgePtr = NULL;
+ return;
+ } else {
+ ep = stack.pop();
+ currentDawgPrefix.resize(currentDawgPrefix.length() - 1);
+ }
+ }
+ edgePtr = ep + 1;
+ } else {
+ stack.push(ep);
+ currentDawgPrefix.push_back(lp->ordToChar(ep->letter));
+ edgePtr = &lp->edges[ep->children];
+ }
+};
+
+static void toLowerCaseInPlace(string & str) {
+ int nChars = str.length();
+ for (int i = 0; i < nChars; i++) {
+ str[i] = tolower(str[i]);
+ }
+}
diff --git a/labb8/lib/StanfordCPPLib/lexicon.h b/labb8/lib/StanfordCPPLib/lexicon.h
new file mode 100755
index 0000000..fea4726
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/lexicon.h
@@ -0,0 +1,366 @@
+/*
+ * File: lexicon.h
+ * ---------------
+ * This file exports the <code>Lexicon</code> class, which is a
+ * compact structure for storing a list of words.
+ */
+
+#ifndef _lexicon_h
+#define _lexicon_h
+
+#include <string>
+#include "foreach.h"
+#include "set.h"
+#include "stack.h"
+
+/*
+ * Class: Lexicon
+ * --------------
+ * This class is used to represent a <b><i>lexicon,</i></b> or word list.
+ * The main difference between a lexicon and a dictionary is that
+ * a lexicon does not provide any mechanism for storing definitions;
+ * the lexicon contains only words, with no associated information.
+ * It is therefore similar to a set of strings, but with a more
+ * space-efficient internal representation. The <code>Lexicon</code>
+ * class supports efficient lookup operations for words and prefixes.
+ *
+ * <p>As an example of the use of the <code>Lexicon</code> class, the
+ * following program lists all the two-letter words in the lexicon
+ * stored in <code>EnglishWords.dat</code>:
+ *
+ *<pre>
+ * int main() {
+ * Lexicon english("EnglishWords.dat");
+ * foreach (string word in english) {
+ * if (word.length() == 2) {
+ * cout << word << endl;
+ * }
+ * }
+ * return 0;
+ * }
+ *</pre>
+ */
+
+#include <cctype>
+
+class Lexicon {
+
+public:
+
+/*
+ * Constructor: Lexicon
+ * Usage: Lexicon lex;
+ * Lexicon lex(filename);
+ * -----------------------------
+ * Initializes a new lexicon. The default constructor creates an empty
+ * lexicon. The second form reads in the contents of the lexicon from
+ * the specified data file. The data file must be in one of two formats:
+ * (1) a space-efficient precompiled binary format or (2) a text file
+ * containing one word per line. The Stanford library distribution
+ * includes a binary lexicon file named <code>English.dat</code>
+ * containing a list of words in English. The standard code pattern
+ * to initialize that lexicon looks like this:
+ *
+ *<pre>
+ * Lexicon english("English.dat");
+ *</pre>
+ */
+
+ Lexicon();
+ Lexicon(std::string filename);
+
+/*
+ * Destructor: ~Lexicon
+ * --------------------
+ * The destructor deallocates any storage associated with the lexicon.
+ */
+
+ virtual ~Lexicon();
+
+/*
+ * Method: size
+ * Usage: int n = lex.size();
+ * --------------------------
+ * Returns the number of words contained in the lexicon.
+ */
+
+ int size() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (lex.isEmpty()) ...
+ * -----------------------------
+ * Returns <code>true</code> if the lexicon contains no words.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: clear
+ * Usage: lex.clear();
+ * -------------------
+ * Removes all words from the lexicon.
+ */
+
+ void clear();
+
+/*
+ * Method: add
+ * Usage: lex.add(word);
+ * ---------------------
+ * Adds the specified word to the lexicon.
+ */
+
+ void add(std::string word);
+
+/*
+ * Method: addWordsFromFile
+ * Usage: lex.addWordsFromFile(filename);
+ * --------------------------------------
+ * Reads the file and adds all of its words to the lexicon.
+ */
+
+ void addWordsFromFile(std::string filename);
+
+/*
+ * Method: contains
+ * Usage: if (lex.contains(word)) ...
+ * ----------------------------------
+ * Returns <code>true</code> if <code>word</code> is contained in the
+ * lexicon. In the <code>Lexicon</code> class, the case of letters is
+ * ignored, so "Zoo" is the same as "ZOO" or "zoo".
+ */
+
+ bool contains(std::string word) const;
+
+/*
+ * Method: containsPrefix
+ * Usage: if (lex.containsPrefix(prefix)) ...
+ * ------------------------------------------
+ * Returns true if any words in the lexicon begin with <code>prefix</code>.
+ * Like <code>containsWord</code>, this method ignores the case of letters
+ * so that "MO" is a prefix of "monkey" or "Monday".
+ */
+
+ bool containsPrefix(std::string prefix) const;
+
+/*
+ * Method: mapAll
+ * Usage: lexicon.mapAll(fn);
+ * --------------------------
+ * Calls the specified function on each word in the lexicon.
+ */
+
+ void mapAll(void (*fn)(std::string)) const;
+ void mapAll(void (*fn)(const std::string &)) const;
+
+ template <typename FunctorType>
+ void mapAll(FunctorType fn) const;
+
+/*
+ * Additional Lexicon operations
+ * -----------------------------
+ * In addition to the methods listed in this interface, the Lexicon
+ * class supports the following operations:
+ *
+ * - Deep copying for the copy constructor and assignment operator
+ * - Iteration using the range-based for statement and STL iterators
+ *
+ * All iteration is guaranteed to proceed in alphabetical order. All
+ * words in the lexicon are stored in lowercase.
+ */
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+private:
+
+#ifdef _WIN32
+#define LITTLE_ENDIAN 1
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+#pragma pack(1)
+ struct Edge {
+#if defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
+ unsigned long letter:5;
+ unsigned long lastEdge:1;
+ unsigned long accept:1;
+ unsigned long unused:1;
+ unsigned long children:24;
+#else
+ unsigned long children:24;
+ unsigned long unused:1;
+ unsigned long accept:1;
+ unsigned long lastEdge:1;
+ unsigned long letter:5;
+#endif
+ };
+#pragma pack()
+
+ Edge *edges, *start;
+ int numEdges, numDawgWords;
+ Set<std::string> otherWords;
+
+public:
+
+/*
+ * Deep copying support
+ * --------------------
+ * This copy constructor and operator= are defined to make a
+ * deep copy, making it possible to pass/return lexicons by value
+ * and assign from one lexicon to another. The entire contents of
+ * the lexicon, including all words, are copied. Making copies is
+ * generally avoided because of the expense and thus, lexicons are
+ * typically passed by reference. When a copy is needed, these
+ * operations are supported.
+ */
+
+ Lexicon(const Lexicon & src);
+ Lexicon & operator=(const Lexicon & src);
+
+/*
+ * Iterator support
+ * ----------------
+ * The classes in the StanfordCPPLib collection implement input
+ * iterators so that they work symmetrically with respect to the
+ * corresponding STL classes.
+ */
+
+ class iterator : public std::iterator<std::input_iterator_tag,std::string> {
+ private:
+ const Lexicon *lp;
+ int index;
+ std::string currentDawgPrefix;
+ std::string currentSetWord;
+ std::string tmpWord;
+ Edge *edgePtr;
+ Stack<Edge *> stack;
+ Set<std::string>::iterator setIterator;
+ Set<std::string>::iterator setEnd;
+
+ void advanceToNextWordInDawg();
+ void advanceToNextWordInSet();
+ void advanceToNextEdge();
+
+ public:
+ iterator() {
+ this->lp = NULL;
+ }
+
+ iterator(const Lexicon *lp, bool endFlag) {
+ this->lp = lp;
+ if (endFlag) {
+ index = lp->size();
+ } else {
+ index = 0;
+ edgePtr = NULL;
+ setIterator = lp->otherWords.begin();
+ setEnd = lp->otherWords.end();
+ currentDawgPrefix = "";
+ currentSetWord = "";
+ advanceToNextWordInDawg();
+ advanceToNextWordInSet();
+ }
+ }
+
+ iterator(const iterator & it) {
+ lp = it.lp;
+ index = it.index;
+ currentDawgPrefix = it.currentDawgPrefix;
+ currentSetWord = it.currentSetWord;
+ edgePtr = it.edgePtr;
+ stack = it.stack;
+ setIterator = it.setIterator;
+ }
+
+ iterator & operator++() {
+ if (edgePtr == NULL) {
+ advanceToNextWordInSet();
+ } else {
+ if (currentSetWord == "" || currentDawgPrefix < currentSetWord) {
+ advanceToNextWordInDawg();
+ } else {
+ advanceToNextWordInSet();
+ }
+ }
+ index++;
+ return *this;
+ }
+
+ iterator operator++(int) {
+ iterator copy(*this);
+ operator++();
+ return copy;
+ }
+
+ bool operator==(const iterator & rhs) {
+ return lp == rhs.lp && index == rhs.index;
+ }
+
+ bool operator!=(const iterator & rhs) {
+ return !(*this == rhs);
+ }
+
+ std::string operator*() {
+ if (edgePtr == NULL) return currentSetWord;
+ if (currentSetWord == "" || currentDawgPrefix < currentSetWord) {
+ return currentDawgPrefix + lp->ordToChar(edgePtr->letter);
+ } else {
+ return currentSetWord;
+ }
+ }
+
+ std::string *operator->() {
+ if (edgePtr == NULL) return &currentSetWord;
+ if (currentSetWord == "" || currentDawgPrefix < currentSetWord) {
+ tmpWord = currentDawgPrefix + lp->ordToChar(edgePtr->letter);
+ return &tmpWord;
+ } else {
+ return &currentSetWord;
+ }
+ }
+
+ };
+
+ iterator begin() const {
+ return iterator(this, false);
+ }
+
+ iterator end() const {
+ return iterator(this, true);
+ }
+
+private:
+
+ Edge *findEdgeForChar(Edge *children, char ch) const;
+ Edge *traceToLastEdge(const std::string & s) const;
+ void readBinaryFile(std::string filename);
+ void deepCopy(const Lexicon & src);
+ int countDawgWords(Edge *start) const;
+
+ unsigned int charToOrd(char ch) const {
+ return ((unsigned int)(tolower(ch) - 'a' + 1));
+ }
+
+ char ordToChar(unsigned int ord) const {
+ return ((char)(ord - 1 + 'a'));
+ }
+
+};
+
+template <typename FunctorType>
+void Lexicon::mapAll(FunctorType fn) const {
+ foreach (std::string word in *this) {
+ fn(word);
+ }
+}
+
+// hashing functions for lexicons; defined in hashmap.cpp
+int hashCode(const Lexicon& l);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/main.cpp b/labb8/lib/StanfordCPPLib/main.cpp
new file mode 100755
index 0000000..6feb8aa
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/main.cpp
@@ -0,0 +1,108 @@
+/*
+ * File: main.cpp
+ * --------------
+ * This file defines a default version of the Main function that takes
+ * the argc and argv arguments. This function must be defined in its
+ * own module to ensure that it is loaded only if the client doesn't
+ * supply one.
+ */
+
+#include <exception>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+int Main(int, char *[]) {
+ extern int Main();
+ return Main();
+}
+
+void __StanfordCPPLib_terminate_handler() {
+ try {
+ throw; // re-throws the exception that already occurred
+ } catch (const std::exception& ex) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** An exception occurred during program execution: \n";
+ msg += " *** ";
+ msg += ex.what();
+ msg += "\n ***\n\n";
+ cerr << msg;
+ throw ex;
+ } catch (std::string str) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A string exception occurred during program execution: \n";
+ msg += " *** \"";
+ msg += str;
+ msg += "\"\n ***\n";
+ cerr << msg;
+ throw str;
+ } catch (char const* str) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A string exception occurred during program execution: \n";
+ msg += " *** \"";
+ msg += str;
+ msg += "\"\n ***\n";
+ cerr << msg;
+ throw str;
+ } catch (int n) {
+ char buf[128];
+ snprintf(buf, 128, "%d", n);
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** An int exception occurred during program execution: \n";
+ msg += " *** ";
+ msg += buf;
+ msg += "\n ***\n\n";
+ cerr << msg;
+ throw n;
+ } catch (long l) {
+ char buf[128];
+ snprintf(buf, 128, "%ld", l);
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A long exception occurred during program execution: \n";
+ msg += " *** ";
+ msg += buf;
+ msg += "\n ***\n\n";
+ cerr << msg;
+ throw l;
+ } catch (char c) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A char exception occurred during program execution: \n";
+ msg += " *** '";
+ msg += c;
+ msg += "'\n ***\n";
+ cerr << msg;
+ throw c;
+ } catch (bool b) {
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A bool exception occurred during program execution: \n";
+ msg += " *** ";
+ msg += (b ? "true" : "false");
+ msg += "\n ***\n\n";
+ cerr << msg;
+ throw b;
+ } catch (double d) {
+ char buf[128];
+ snprintf(buf, 128, "%lf", d);
+ string msg = "\n ***\n";
+ msg += " *** STANFORD C++ LIBRARY \n";
+ msg += " *** A double exception occurred during program execution: \n";
+ msg += " *** ";
+ msg += buf;
+ msg += "\n ***\n\n";
+ cerr << msg;
+ throw d;
+ }
+ abort();
+}
+
+void __StanfordCPPLib_set_terminate() {
+ set_terminate(__StanfordCPPLib_terminate_handler);
+}
diff --git a/labb8/lib/StanfordCPPLib/map.h b/labb8/lib/StanfordCPPLib/map.h
new file mode 100755
index 0000000..663de03
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/map.h
@@ -0,0 +1,910 @@
+/*
+ * File: map.h
+ * -----------
+ * This file exports the template class <code>Map</code>, which
+ * maintains a collection of <i>key</i>-<i>value</i> pairs.
+ */
+
+#ifndef _map_h
+#define _map_h
+
+#include <cstdlib>
+#include "foreach.h"
+#include "stack.h"
+#include "vector.h"
+
+/*
+ * Class: Map<KeyType,ValueType>
+ * -----------------------------
+ * This class maintains an association between <b><i>keys</i></b> and
+ * <b><i>values</i></b>. The types used for keys and values are
+ * specified using templates, which makes it possible to use
+ * this structure with any data type.
+ */
+
+template <typename KeyType, typename ValueType>
+class Map {
+
+public:
+
+/*
+ * Constructor: Map
+ * Usage: Map<KeyType,ValueType> map;
+ * ----------------------------------
+ * Initializes a new empty map that associates keys and values of the
+ * specified types.
+ */
+
+ Map();
+
+/*
+ * Destructor: ~Map
+ * ----------------
+ * Frees any heap storage associated with this map.
+ */
+
+ virtual ~Map();
+
+/*
+ * Method: size
+ * Usage: int nEntries = map.size();
+ * ---------------------------------
+ * Returns the number of entries in this map.
+ */
+
+ int size() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (map.isEmpty()) ...
+ * -----------------------------
+ * Returns <code>true</code> if this map contains no entries.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: put
+ * Usage: map.put(key, value);
+ * ---------------------------
+ * Associates <code>key</code> with <code>value</code> in this map.
+ * Any previous value associated with <code>key</code> is replaced
+ * by the new value.
+ */
+
+ void put(const KeyType & key, const ValueType & value);
+
+/*
+ * Method: get
+ * Usage: ValueType value = map.get(key);
+ * --------------------------------------
+ * Returns the value associated with <code>key</code> in this map.
+ * If <code>key</code> is not found, <code>get</code> returns the
+ * default value for <code>ValueType</code>.
+ */
+
+ ValueType get(const KeyType & key) const;
+
+/*
+ * Method: containsKey
+ * Usage: if (map.containsKey(key)) ...
+ * ------------------------------------
+ * Returns <code>true</code> if there is an entry for <code>key</code>
+ * in this map.
+ */
+
+ bool containsKey(const KeyType & key) const;
+
+/*
+ * Method: remove
+ * Usage: map.remove(key);
+ * -----------------------
+ * Removes any entry for <code>key</code> from this map.
+ */
+
+ void remove(const KeyType & key);
+
+/*
+ * Method: clear
+ * Usage: map.clear();
+ * -------------------
+ * Removes all entries from this map.
+ */
+
+ void clear();
+
+/*
+ * Method: keys
+ * Usage: Vector<KeyType> keys = map.keys();
+ * -------------------------------------------
+ * Returns a collection containing all keys in this map.
+ */
+
+ Vector<KeyType> keys() const;
+
+/*
+ * Method: values
+ * Usage: Vector<ValueType> values = map.values();
+ * -------------------------------------------
+ * Returns a collection containing all values in this map.
+ */
+
+ Vector<ValueType> values() const;
+
+/*
+ * Operator: []
+ * Usage: map[key]
+ * ---------------
+ * Selects the value associated with <code>key</code>. This syntax
+ * makes it easy to think of a map as an "associative array"
+ * indexed by the key type. If <code>key</code> is already present
+ * in the map, this function returns a reference to its associated
+ * value. If key is not present in the map, a new entry is created
+ * whose value is set to the default for the value type.
+ */
+
+ ValueType & operator[](const KeyType & key);
+ ValueType operator[](const KeyType & key) const;
+
+/*
+ * Method: toString
+ * Usage: string str = map.toString();
+ * -----------------------------------
+ * Converts the map to a printable string representation.
+ */
+
+ std::string toString();
+
+/*
+ * Method: mapAll
+ * Usage: map.mapAll(fn);
+ * ----------------------
+ * Iterates through the map entries and calls <code>fn(key, value)</code>
+ * for each one. The keys are processed in ascending order, as defined
+ * by the comparison function.
+ */
+
+ void mapAll(void (*fn)(KeyType, ValueType)) const;
+ void mapAll(void (*fn)(const KeyType &, const ValueType &)) const;
+ template <typename FunctorType>
+ void mapAll(FunctorType fn) const;
+
+/*
+ * Additional Map operations
+ * -------------------------
+ * In addition to the methods listed in this interface, the Map
+ * class supports the following operations:
+ *
+ * - Stream I/O using the << and >> operators
+ * - Deep copying for the copy constructor and assignment operator
+ * - Iteration using the range-based for statement and STL iterators
+ *
+ * All iteration is guaranteed to proceed in the order established by
+ * the comparison function passed to the constructor, which ordinarily
+ * matches the order of the key type.
+ */
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+/*
+ * Implementation notes:
+ * ---------------------
+ * The map class is represented using a binary search tree. The
+ * specific implementation used here is the classic AVL algorithm
+ * developed by Georgii Adel'son-Vel'skii and Evgenii Landis in 1962.
+ */
+
+private:
+
+/* Constant definitions */
+
+ static const int BST_LEFT_HEAVY = -1;
+ static const int BST_IN_BALANCE = 0;
+ static const int BST_RIGHT_HEAVY = +1;
+
+/* Type definition for nodes in the binary search tree */
+
+ struct BSTNode {
+ KeyType key; /* The key stored in this node */
+ ValueType value; /* The corresponding value */
+ BSTNode *left; /* Subtree containing all smaller keys */
+ BSTNode *right; /* Subtree containing all larger keys */
+ int bf; /* AVL balance factor */
+ };
+
+/*
+ * Implementation notes: Comparator
+ * --------------------------------
+ * The Comparator class encapsulates a functor that compares two values
+ * of KeyType. In contrast to the classes in the STL, all of which embed
+ * the comparator in the type, the Map class and its derivatives pass an
+ * optional Comparator value. While this strategy results in a more
+ * complex implementation, it has the advantage of allowing maps and sets
+ * to carry their own comparators without forcing the client to include
+ * the comparator in the template declaration. This simplification is
+ * particularly important for the Graph class.
+ *
+ * The allocation is required in the TemplateComparator class because
+ * the type std::binary_function has subclasses but does not define a
+ * virtual destructor.
+ */
+
+ class Comparator {
+ public:
+ virtual ~Comparator() { }
+ virtual bool lessThan(const KeyType & k1, const KeyType & k2) = 0;
+ virtual Comparator *clone() = 0;
+ };
+
+ template <typename CompareType>
+ class TemplateComparator : public Comparator {
+ public:
+ TemplateComparator(CompareType cmp) {
+ this->cmp = new CompareType(cmp);
+ }
+
+ virtual bool lessThan(const KeyType & k1, const KeyType & k2) {
+ return (*cmp)(k1, k2);
+ }
+
+ virtual Comparator *clone() {
+ return new TemplateComparator<CompareType>(*cmp);
+ }
+
+ private:
+ CompareType *cmp;
+ };
+
+ Comparator & getComparator() const {
+ return *cmpp;
+ }
+
+/* Instance variables */
+
+ BSTNode *root; /* Pointer to the root of the tree */
+ int nodeCount; /* Number of entries in the map */
+ Comparator *cmpp; /* Pointer to the comparator */
+
+ int (*cmpFn)(const KeyType &, const KeyType &);
+
+/* Private methods */
+
+/*
+ * Implementation notes: findNode(t, key)
+ * --------------------------------------
+ * Searches the tree rooted at t to find the specified key, searching
+ * in the left or right subtree, as approriate. If a matching node
+ * is found, findNode returns a pointer to the value cell in that node.
+ * If no matching node exists in the tree, findNode returns NULL.
+ */
+
+ ValueType *findNode(BSTNode *t, const KeyType & key) const {
+ if (t == NULL) return NULL;
+ int sign = compareKeys(key, t->key);
+ if (sign == 0) return &t->value;
+ if (sign < 0) {
+ return findNode(t->left, key);
+ } else {
+ return findNode(t->right, key);
+ }
+ }
+
+/*
+ * Implementation notes: addNode(t, key, heightFlag)
+ * -------------------------------------------------
+ * Searches the tree rooted at t to find the specified key, searching
+ * in the left or right subtree, as approriate. If a matching node
+ * is found, addNode returns a pointer to the value cell in that node,
+ * just like findNode. If no matching node exists in the tree, addNode
+ * creates a new node with a default value. The heightFlag reference
+ * parameter returns a bool indicating whether the height of the tree
+ * was changed by this operation.
+ */
+
+ ValueType *addNode(BSTNode * & t, const KeyType & key, bool & heightFlag) {
+ heightFlag = false;
+ if (t == NULL) {
+ t = new BSTNode();
+ t->key = key;
+ t->value = ValueType();
+ t->bf = BST_IN_BALANCE;
+ t->left = t->right = NULL;
+ heightFlag = true;
+ nodeCount++;
+ return &t->value;
+ }
+ int sign = compareKeys(key, t->key);
+ if (sign == 0) return &t->value;
+ ValueType *vp = NULL;
+ int bfDelta = BST_IN_BALANCE;
+ if (sign < 0) {
+ vp = addNode(t->left, key, heightFlag);
+ if (heightFlag) bfDelta = BST_LEFT_HEAVY;
+ } else {
+ vp = addNode(t->right, key, heightFlag);
+ if (heightFlag) bfDelta = BST_RIGHT_HEAVY;
+ }
+ updateBF(t, bfDelta);
+ heightFlag = (bfDelta != 0 && t->bf != BST_IN_BALANCE);
+ return vp;
+ }
+
+/*
+ * Implementation notes: removeNode(t, key)
+ * ----------------------------------------
+ * Removes the node containing the specified key from the tree rooted
+ * at t. The return value is true if the height of this subtree
+ * changes. The removeTargetNode method does the actual deletion.
+ */
+
+ bool removeNode(BSTNode * & t, const KeyType & key) {
+ if (t == NULL) return false;
+ int sign = compareKeys(key, t->key);
+ if (sign == 0) return removeTargetNode(t);
+ int bfDelta = BST_IN_BALANCE;
+ if (sign < 0) {
+ if (removeNode(t->left, key)) bfDelta = BST_RIGHT_HEAVY;
+ } else {
+ if (removeNode(t->right, key)) bfDelta = BST_LEFT_HEAVY;
+ }
+ updateBF(t, bfDelta);
+ return bfDelta != 0 && t->bf == BST_IN_BALANCE;
+ }
+
+/*
+ * Implementation notes: removeTargetNode(t)
+ * -----------------------------------------
+ * Removes the node which is passed by reference as t. The easy case
+ * occurs when either (or both) of the children is NULL; all you need
+ * to do is replace the node with its non-NULL child, if any. If both
+ * children are non-NULL, this code finds the rightmost descendent of
+ * the left child; this node may not be a leaf, but will have no right
+ * child. Its left child replaces it in the tree, after which the
+ * replacement data is moved to the position occupied by the target node.
+ */
+
+ bool removeTargetNode(BSTNode * & t) {
+ BSTNode *toDelete = t;
+ if (t->left == NULL) {
+ t = t->right;
+ delete toDelete;
+ nodeCount--;
+ return true;
+ } else if (t->right == NULL) {
+ t = t->left;
+ delete toDelete;
+ nodeCount--;
+ return true;
+ } else {
+ BSTNode *successor = t->left;
+ while (successor->right != NULL) {
+ successor = successor->right;
+ }
+ t->key = successor->key;
+ t->value = successor->value;
+ if (removeNode(t->left, successor->key)) {
+ updateBF(t, BST_RIGHT_HEAVY);
+ return (t->bf == BST_IN_BALANCE);
+ }
+ return false;
+ }
+ }
+
+/*
+ * Implementation notes: updateBF(t, bfDelta)
+ * ------------------------------------------
+ * Updates the balance factor in the node and rebalances the tree
+ * if necessary.
+ */
+
+ void updateBF(BSTNode * & t, int bfDelta) {
+ t->bf += bfDelta;
+ if (t->bf < BST_LEFT_HEAVY) {
+ fixLeftImbalance(t);
+ } else if (t->bf > BST_RIGHT_HEAVY) {
+ fixRightImbalance(t);
+ }
+ }
+
+/*
+ * Implementation notes: fixLeftImbalance(t)
+ * -----------------------------------------
+ * This function is called when a node has been found that is out
+ * of balance with the longer subtree on the left. Depending on
+ * the balance factor of the left child, the code performs a
+ * single or double rotation.
+ */
+
+ void fixLeftImbalance(BSTNode * & t) {
+ BSTNode *child = t->left;
+ if (child->bf == BST_RIGHT_HEAVY) {
+ int oldBF = child->right->bf;
+ rotateLeft(t->left);
+ rotateRight(t);
+ t->bf = BST_IN_BALANCE;
+ switch (oldBF) {
+ case BST_LEFT_HEAVY:
+ t->left->bf = BST_IN_BALANCE;
+ t->right->bf = BST_RIGHT_HEAVY;
+ break;
+ case BST_IN_BALANCE:
+ t->left->bf = t->right->bf = BST_IN_BALANCE;
+ break;
+ case BST_RIGHT_HEAVY:
+ t->left->bf = BST_LEFT_HEAVY;
+ t->right->bf = BST_IN_BALANCE;
+ break;
+ }
+ } else if (child->bf == BST_IN_BALANCE) {
+ rotateRight(t);
+ t->bf = BST_RIGHT_HEAVY;
+ t->right->bf = BST_LEFT_HEAVY;
+ } else {
+ rotateRight(t);
+ t->right->bf = t->bf = BST_IN_BALANCE;
+ }
+ }
+
+/*
+ * Implementation notes: rotateLeft(t)
+ * -----------------------------------
+ * This function performs a single left rotation of the tree
+ * that is passed by reference. The balance factors
+ * are unchanged by this function and must be corrected at a
+ * higher level of the algorithm.
+ */
+
+ void rotateLeft(BSTNode * & t) {
+ BSTNode *child = t->right;
+ t->right = child->left;
+ child->left = t;
+ t = child;
+ }
+
+/*
+ * Implementation notes: fixRightImbalance(t)
+ * ------------------------------------------
+ * This function is called when a node has been found that
+ * is out of balance with the longer subtree on the right.
+ * Depending on the balance factor of the right child, the
+ * code performs a single or double rotation.
+ */
+
+ void fixRightImbalance(BSTNode * & t) {
+ BSTNode *child = t->right;
+ if (child->bf == BST_LEFT_HEAVY) {
+ int oldBF = child->left->bf;
+ rotateRight(t->right);
+ rotateLeft(t);
+ t->bf = BST_IN_BALANCE;
+ switch (oldBF) {
+ case BST_LEFT_HEAVY:
+ t->left->bf = BST_IN_BALANCE;
+ t->right->bf = BST_RIGHT_HEAVY;
+ break;
+ case BST_IN_BALANCE:
+ t->left->bf = t->right->bf = BST_IN_BALANCE;
+ break;
+ case BST_RIGHT_HEAVY:
+ t->left->bf = BST_LEFT_HEAVY;
+ t->right->bf = BST_IN_BALANCE;
+ break;
+ }
+ } else if (child->bf == BST_IN_BALANCE) {
+ rotateLeft(t);
+ t->bf = BST_LEFT_HEAVY;
+ t->left->bf = BST_RIGHT_HEAVY;
+ } else {
+ rotateLeft(t);
+ t->left->bf = t->bf = BST_IN_BALANCE;
+ }
+ }
+
+/*
+ * Implementation notes: rotateRight(t)
+ * ------------------------------------
+ * This function performs a single right rotation of the tree
+ * that is passed by reference. The balance factors
+ * are unchanged by this function and must be corrected at a
+ * higher level of the algorithm.
+ */
+
+ void rotateRight(BSTNode * & t) {
+
+ BSTNode *child = t->left;
+ t->left = child->right;
+ child->right = t;
+ t = child;
+ }
+
+/*
+ * Implementation notes: deleteTree(t)
+ * -----------------------------------
+ * Deletes all the nodes in the tree.
+ */
+
+ void deleteTree(BSTNode *t) {
+ if (t != NULL) {
+ deleteTree(t->left);
+ deleteTree(t->right);
+ delete t;
+ }
+ }
+
+/*
+ * Implementation notes: mapAll
+ * ----------------------------
+ * Calls fn(key, value) for every key-value pair in the tree.
+ */
+
+ void mapAll(BSTNode *t, void (*fn)(KeyType, ValueType)) const {
+ if (t != NULL) {
+ mapAll(t->left, fn);
+ fn(t->key, t->value);
+ mapAll(t->right, fn);
+ }
+ }
+
+ void mapAll(BSTNode *t,
+ void (*fn)(const KeyType &, const ValueType &)) const {
+ if (t != NULL) {
+ mapAll(t->left, fn);
+ fn(t->key, t->value);
+ mapAll(t->right, fn);
+ }
+ }
+
+ template <typename FunctorType>
+ void mapAll(BSTNode *t, FunctorType fn) const {
+ if (t != NULL) {
+ mapAll(t->left, fn);
+ fn(t->key, t->value);
+ mapAll(t->right, fn);
+ }
+ }
+
+ void deepCopy(const Map & other) {
+ root = copyTree(other.root);
+ nodeCount = other.nodeCount;
+ cmpp = (other.cmpp == NULL) ? NULL : other.cmpp->clone();
+ }
+
+ BSTNode *copyTree(BSTNode * const t) {
+ if (t == NULL) return NULL;
+ BSTNode *np = new BSTNode();
+ np->key = t->key;
+ np->value = t->value;
+ np->bf = t->bf;
+ np->left = copyTree(t->left);
+ np->right = copyTree(t->right);
+ return np;
+ }
+
+public:
+
+/*
+ * Hidden features
+ * ---------------
+ * The remainder of this file consists of the code required to
+ * support deep copying and iteration. Including these methods in
+ * the public portion of the interface would make that interface more
+ * difficult to understand for the average client.
+ */
+
+/* Extended constructors */
+
+ template <typename CompareType>
+ explicit Map(CompareType cmp) {
+ root = NULL;
+ nodeCount = 0;
+ cmpp = new TemplateComparator<CompareType>(cmp);
+ }
+
+/*
+ * Implementation notes: compareKeys(k1, k2)
+ * -----------------------------------------
+ * Compares the keys k1 and k2 and returns an integer (-1, 0, or +1)
+ * depending on whether k1 < k2, k1 == k2, or k1 > k2, respectively.
+ */
+
+ int compareKeys(const KeyType & k1, const KeyType & k2) const {
+ if (cmpp->lessThan(k1, k2)) return -1;
+ if (cmpp->lessThan(k2, k1)) return +1;
+ return 0;
+ }
+
+/*
+ * Deep copying support
+ * --------------------
+ * This copy constructor and operator= are defined to make a
+ * deep copy, making it possible to pass/return maps by value
+ * and assign from one map to another.
+ */
+
+ Map & operator=(const Map & src) {
+ if (this != &src) {
+ clear();
+ deepCopy(src);
+ }
+ return *this;
+ }
+
+ Map(const Map & src) {
+ deepCopy(src);
+ }
+
+/*
+ * Iterator support
+ * ----------------
+ * The classes in the StanfordCPPLib collection implement input
+ * iterators so that they work symmetrically with respect to the
+ * corresponding STL classes.
+ */
+
+ class iterator : public std::iterator<std::input_iterator_tag,KeyType> {
+
+ private:
+
+ struct NodeMarker {
+ BSTNode *np;
+ bool processed;
+ };
+
+ const Map *mp; /* Pointer to the map */
+ int index; /* Index of current element */
+ Stack<NodeMarker> stack; /* Stack of unprocessed nodes */
+
+ void findLeftmostChild() {
+ BSTNode *np = stack.peek().np;
+ if (np == NULL) return;
+ while (np->left != NULL) {
+ NodeMarker marker = { np->left, false };
+ stack.push(marker);
+ np = np->left;
+ }
+ }
+
+ public:
+
+ iterator() {
+ /* Empty */
+ }
+
+ iterator(const Map *mp, bool end) {
+ this->mp = mp;
+ if (end || mp->nodeCount == 0) {
+ index = mp->nodeCount;
+ } else {
+ index = 0;
+ NodeMarker marker = { mp->root, false };
+ stack.push(marker);
+ findLeftmostChild();
+ }
+ }
+
+ iterator(const iterator & it) {
+ mp = it.mp;
+ index = it.index;
+ stack = it.stack;
+ }
+
+ iterator & operator++() {
+ NodeMarker marker = stack.pop();
+ BSTNode *np = marker.np;
+ if (np->right == NULL) {
+ while (!stack.isEmpty() && stack.peek().processed) {
+ stack.pop();
+ }
+ } else {
+ marker.processed = true;
+ stack.push(marker);
+ marker.np = np->right;
+ marker.processed = false;
+ stack.push(marker);
+ findLeftmostChild();
+ }
+ index++;
+ return *this;
+ }
+
+ iterator operator++(int) {
+ iterator copy(*this);
+ operator++();
+ return copy;
+ }
+
+ bool operator==(const iterator & rhs) {
+ return mp == rhs.mp && index == rhs.index;
+ }
+
+ bool operator!=(const iterator & rhs) {
+ return !(*this == rhs);
+ }
+
+ KeyType operator*() {
+ return stack.peek().np->key;
+ }
+
+ KeyType *operator->() {
+ return &stack.peek().np->key;
+ }
+
+ friend class Map;
+
+ };
+
+ iterator begin() const {
+ return iterator(this, false);
+ }
+
+ iterator end() const {
+ return iterator(this, true);
+ }
+
+};
+
+template <typename KeyType, typename ValueType>
+Map<KeyType,ValueType>::Map() {
+ root = NULL;
+ nodeCount = 0;
+ cmpp = new TemplateComparator< less<KeyType> >(less<KeyType>());
+}
+
+template <typename KeyType, typename ValueType>
+Map<KeyType,ValueType>::~Map() {
+ if (cmpp != NULL) delete cmpp;
+ deleteTree(root);
+}
+
+template <typename KeyType, typename ValueType>
+int Map<KeyType,ValueType>::size() const {
+ return nodeCount;
+}
+
+template <typename KeyType, typename ValueType>
+bool Map<KeyType,ValueType>::isEmpty() const {
+ return nodeCount == 0;
+}
+
+template <typename KeyType, typename ValueType>
+void Map<KeyType,ValueType>::put(const KeyType & key,
+ const ValueType & value) {
+ bool dummy;
+ *addNode(root, key, dummy) = value;
+}
+
+template <typename KeyType, typename ValueType>
+ValueType Map<KeyType,ValueType>::get(const KeyType & key) const {
+ ValueType *vp = findNode(root, key);
+ if (vp == NULL) return ValueType();
+ return *vp;
+}
+
+template <typename KeyType, typename ValueType>
+void Map<KeyType,ValueType>::remove(const KeyType & key) {
+ removeNode(root, key);
+}
+
+template <typename KeyType, typename ValueType>
+void Map<KeyType,ValueType>::clear() {
+ deleteTree(root);
+ root = NULL;
+ nodeCount = 0;
+}
+
+template <typename KeyType, typename ValueType>
+bool Map<KeyType,ValueType>::containsKey(const KeyType & key) const {
+ return findNode(root, key) != NULL;
+}
+
+template <typename KeyType, typename ValueType>
+ValueType & Map<KeyType,ValueType>::operator[](const KeyType & key) {
+ bool dummy;
+ return *addNode(root, key, dummy);
+}
+
+template <typename KeyType, typename ValueType>
+ValueType Map<KeyType,ValueType>::operator[](const KeyType & key) const {
+ return get(key);
+}
+
+template <typename KeyType, typename ValueType>
+void Map<KeyType,ValueType>::mapAll(void (*fn)(KeyType, ValueType)) const {
+ mapAll(root, fn);
+}
+
+template <typename KeyType, typename ValueType>
+void Map<KeyType,ValueType>::mapAll(void (*fn)(const KeyType &,
+ const ValueType &)) const {
+ mapAll(root, fn);
+}
+
+template <typename KeyType, typename ValueType>
+template <typename FunctorType>
+void Map<KeyType,ValueType>::mapAll(FunctorType fn) const {
+ mapAll(root, fn);
+}
+
+template <typename KeyType, typename ValueType>
+std::string Map<KeyType,ValueType>::toString() {
+ ostringstream os;
+ os << *this;
+ return os.str();
+}
+
+template <typename KeyType,typename ValueType>
+Vector<KeyType> Map<KeyType,ValueType>::keys() const {
+ Vector<KeyType> keyset;
+ foreach (KeyType key in *this) {
+ keyset.add(key);
+ }
+ return keyset;
+}
+
+template <typename KeyType,typename ValueType>
+Vector<ValueType> Map<KeyType,ValueType>::values() const {
+ Vector<ValueType> values;
+ foreach (KeyType key in *this) {
+ values.add(this->get(key));
+ }
+ return values;
+}
+
+/*
+ * Implementation notes: << and >>
+ * -------------------------------
+ * The insertion and extraction operators use the template facilities in
+ * strlib.h to read and write generic values in a way that treats strings
+ * specially.
+ */
+
+template <typename KeyType, typename ValueType>
+std::ostream & operator<<(std::ostream & os,
+ const Map<KeyType,ValueType> & map) {
+ os << "{";
+ typename Map<KeyType,ValueType>::iterator begin = map.begin();
+ typename Map<KeyType,ValueType>::iterator end = map.end();
+ typename Map<KeyType,ValueType>::iterator it = begin;
+ while (it != end) {
+ if (it != begin) os << ", ";
+ writeGenericValue(os, *it, false);
+ os << ":";
+ writeGenericValue(os, map[*it], false);
+ ++it;
+ }
+ return os << "}";
+}
+
+template <typename KeyType, typename ValueType>
+std::istream & operator>>(std::istream & is, Map<KeyType,ValueType> & map) {
+ char ch;
+ is >> ch;
+ if (ch != '{') error("operator >>: Missing {");
+ map.clear();
+ is >> ch;
+ if (ch != '}') {
+ is.unget();
+ while (true) {
+ KeyType key;
+ readGenericValue(is, key);
+ is >> ch;
+ if (ch != ':') error("operator >>: Missing colon after key");
+ ValueType value;
+ readGenericValue(is, value);
+ map[key] = value;
+ is >> ch;
+ if (ch == '}') break;
+ if (ch != ',') {
+ error(std::string("operator >>: Unexpected character ") + ch);
+ }
+ }
+ }
+ return is;
+}
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/platform.cpp b/labb8/lib/StanfordCPPLib/platform.cpp
new file mode 100755
index 0000000..d24140e
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/platform.cpp
@@ -0,0 +1,1417 @@
+/*
+ * File: platform.cpp
+ * ------------------
+ * This file implements the platform interface by passing commands to
+ * a Java back end that manages the display.
+ */
+
+#ifdef _WIN32
+# include <windows.h>
+# include <tchar.h>
+# undef MOUSE_EVENT
+# undef KEY_EVENT
+# undef MOUSE_MOVED
+# undef HELP_KEY
+#else
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <dirent.h>
+# include <errno.h>
+# include <pwd.h>
+# include <unistd.h>
+static bool tracePipe;
+static int pin;
+static int pout;
+#endif
+
+#include <algorithm>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+#include "error.h"
+#include "filelib.h"
+#include "gevents.h"
+#include "gtimer.h"
+#include "gtypes.h"
+#include "hashmap.h"
+#include "queue.h"
+#include "platform.h"
+#include "stack.h"
+#include "strlib.h"
+#include "tokenscanner.h"
+#include "vector.h"
+
+using namespace std;
+
+static string getLineConsole();
+static void putConsole(const string & str);
+static void endLineConsole();
+static void echoConsole(const string & str);
+static void fileLogConsole(const string & str);
+static int scanInt(TokenScanner & scanner);
+static double scanDouble(TokenScanner & scanner);
+static GDimension scanDimension(const string & str);
+static GRectangle scanRectangle(const string & str);
+
+class ConsoleStreambuf : public streambuf {
+
+private:
+
+/* Constants */
+
+ static const int BUFFER_SIZE = 1024;
+
+/* Instance variables */
+
+ char inBuffer[BUFFER_SIZE];
+ char outBuffer[BUFFER_SIZE];
+
+public:
+
+ ConsoleStreambuf() {
+ setg(inBuffer, inBuffer, inBuffer);
+ setp(outBuffer, outBuffer + BUFFER_SIZE);
+ }
+
+ ~ConsoleStreambuf() {
+ /* Empty */
+ }
+
+ virtual int underflow() {
+ // Allow long strings at some point
+ string line = getLineConsole();
+ int n = line.length();
+ if (n + 1 >= BUFFER_SIZE) error("String too long");
+ for (int i = 0; i < n; i++) {
+ inBuffer[i] = line[i];
+ }
+ inBuffer[n++] = '\n';
+ inBuffer[n] = '\0';
+ setg(inBuffer, inBuffer, inBuffer + n);
+ return inBuffer[0];
+ }
+
+ virtual int overflow(int ch = EOF) {
+ string line = "";
+ for (char *cp = pbase(); cp < pptr(); cp++) {
+ if (*cp == '\n') {
+ putConsole(line);
+ endLineConsole();
+ line = "";
+ } else {
+ line += *cp;
+ }
+ }
+ if (line != "") {
+ putConsole(line);
+ }
+ setp(outBuffer, outBuffer + BUFFER_SIZE);
+ if (ch != EOF) {
+ outBuffer[0] = ch;
+ pbump(1);
+ }
+ return ch != EOF;
+ }
+
+ virtual int sync() {
+ return overflow();
+ }
+};
+
+/* Private data */
+
+static Queue<GEvent> eventQueue;
+static HashMap<string,GTimerData *> timerTable;
+static HashMap<string,GWindowData *> windowTable;
+static HashMap<string,GObject *> sourceTable;
+static HashMap<string,string> optionTable;
+static string programName;
+static ofstream logfile;
+static streambuf* cin_old_buf;
+static streambuf* cout_old_buf;
+static ConsoleStreambuf* cinout_new_buf;
+
+
+#ifdef _WIN32
+static HANDLE rdFromJBE = NULL;
+static HANDLE wrFromJBE = NULL;
+static HANDLE rdToJBE = NULL;
+static HANDLE wrToJBE = NULL;
+#endif
+
+/* Prototypes */
+
+static void initPipe();
+static void putPipe(string line);
+static string getPipe();
+static string getResult();
+static void getStatus();
+static GEvent parseEvent(string line);
+static GEvent parseMouseEvent(TokenScanner & scanner, EventType type);
+static GEvent parseKeyEvent(TokenScanner & scanner, EventType type);
+static GEvent parseTimerEvent(TokenScanner & scanner, EventType type);
+static GEvent parseWindowEvent(TokenScanner & scanner, EventType type);
+static GEvent parseActionEvent(TokenScanner & scanner, EventType type);
+
+/* Implementation of the Platform class */
+
+Platform::Platform() {
+ /* Empty */
+}
+
+Platform::~Platform() {
+ /* Empty */
+}
+
+/* Unix implementations of filelib.h primitives */
+
+#ifndef _WIN32
+
+bool Platform::fileExists(string filename) {
+ struct stat fileInfo;
+ return stat(filename.c_str(), &fileInfo) == 0;
+}
+
+bool Platform::isFile(string filename) {
+ struct stat fileInfo;
+ if (stat(filename.c_str(), &fileInfo) != 0) return false;
+ return S_ISREG(fileInfo.st_mode) != 0;
+}
+
+bool Platform::isSymbolicLink(string filename) {
+ struct stat fileInfo;
+ if (stat(filename.c_str(), &fileInfo) != 0) return false;
+ return S_ISLNK(fileInfo.st_mode) != 0;
+}
+
+bool Platform::isDirectory(string filename) {
+ struct stat fileInfo;
+ if (stat(filename.c_str(), &fileInfo) != 0) return false;
+ return S_ISDIR(fileInfo.st_mode) != 0;
+}
+
+void Platform::setCurrentDirectory(string path) {
+ if (chdir(path.c_str()) == 0) {
+ string msg = "setCurrentDirectory: ";
+ string err = string(strerror(errno));
+ error(msg + err);
+ }
+}
+
+string Platform::getCurrentDirectory() {
+ char *cwd = getcwd(NULL, 0);
+ if (cwd == NULL) {
+ string msg = "getCurrentDirectory: ";
+ string err = string(strerror(errno));
+ error(msg + err);
+ }
+ string result = string(cwd);
+ free(cwd);
+ return result;
+}
+
+void Platform::createDirectory(string path) {
+ if (endsWith(path, "/")) {
+ path = path.substr(0, path.length() - 2);
+ }
+ if (mkdir(path.c_str(), 0777) != 0) {
+ if (errno == EEXIST && isDirectory(path)) return;
+ string msg = "createDirectory: ";
+ string err = string(strerror(errno));
+ error(msg + err);
+ }
+}
+
+string Platform::getDirectoryPathSeparator() {
+ return "/";
+}
+
+string Platform::getSearchPathSeparator() {
+ return ":";
+}
+
+string Platform::expandPathname(string filename) {
+ if (filename == "") return "";
+ int len = filename.length();
+ if (filename[0] == '~') {
+ int spos = 1;
+ while (spos < len && filename[spos] != '\\' && filename[spos] != '/') {
+ spos++;
+ }
+ char *homedir = NULL;
+ if (spos == 1) {
+ homedir = getenv("HOME");
+ if (homedir == NULL) homedir = getpwuid(getuid())->pw_dir;
+ } else {
+ struct passwd *pw = getpwnam(filename.substr(1, spos - 1).c_str());
+ if (pw == NULL) error("expandPathname: No such user");
+ homedir = pw->pw_dir;
+ }
+ filename = string(homedir) + filename.substr(spos);
+ len = filename.length();
+ }
+ for (int i = 0; i < len; i++) {
+ if (filename[i] == '\\') filename[i] = '/';
+ }
+ return filename;
+}
+
+void Platform::listDirectory(string path, vector<string> & list) {
+ if (path == "") path = ".";
+ DIR *dir = opendir(path.c_str());
+ if (dir == NULL) error(string("listDirectory: Can't open ") + path);
+ list.clear();
+ while (true) {
+ struct dirent *ep = readdir(dir);
+ if (ep == NULL) break;
+ string name = string(ep->d_name);
+ if (name != "." && name != "..") list.push_back(name);
+ }
+ closedir(dir);
+ sort(list.begin(), list.end());
+}
+
+#else
+
+bool Platform::fileExists(string filename) {
+ return GetFileAttributesA(filename.c_str()) != INVALID_FILE_ATTRIBUTES;
+}
+
+bool Platform::isFile(string filename) {
+ DWORD attr = GetFileAttributesA(filename.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_NORMAL);
+}
+
+bool Platform::isSymbolicLink(string filename) {
+ DWORD attr = GetFileAttributesA(filename.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES
+ && (attr & FILE_ATTRIBUTE_REPARSE_POINT);
+}
+
+bool Platform::isDirectory(string filename) {
+ DWORD attr = GetFileAttributesA(filename.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+void Platform::setCurrentDirectory(string path) {
+ if (!isDirectory(path) || !SetCurrentDirectoryA(path.c_str())) {
+ error("setCurrentDirectory: Can't change to " + path);
+ }
+}
+
+string Platform::getCurrentDirectory() {
+ char path[MAX_PATH + 1];
+ int n = GetCurrentDirectoryA(MAX_PATH + 1, path);
+ return string(path, n);
+}
+
+void Platform::createDirectory(string path) {
+ if (!CreateDirectoryA(path.c_str(), NULL)) {
+ error("createDirectory: Can't create " + path);
+ }
+}
+
+string Platform::getDirectoryPathSeparator() {
+ return "\\";
+}
+
+string Platform::getSearchPathSeparator() {
+ return ";";
+}
+
+string Platform::expandPathname(string filename) {
+ if (filename == "") return "";
+ int len = filename.length();
+ for (int i = 0; i < len; i++) {
+ if (filename[i] == '/') filename[i] = '\\';
+ }
+ return filename;
+}
+
+void Platform::listDirectory(string path, vector<string> & list) {
+ if (path == "") path = ".";
+ string pattern = path + "\\*.*";
+ WIN32_FIND_DATAA fd;
+ HANDLE h = FindFirstFileA(pattern.c_str(), &fd);
+ if (h == INVALID_HANDLE_VALUE) {
+ error("listDirectory: Can't list directory");
+ }
+ list.clear();
+ while (true) {
+ string name = string(fd.cFileName);
+ if (name != "." && name != "..") list.push_back(name);
+ if (!FindNextFileA(h, &fd)) break;
+ }
+ FindClose(h);
+ sort(list.begin(), list.end());
+}
+
+#endif
+
+string Platform::openFileDialog(string title, string mode, string path) {
+ ostringstream os;
+ os << "File.openFileDialog(";
+ writeQuotedString(os, title);
+ os << ", \"" << mode << "\", \"" << path << "\")";
+ putPipe(os.str());
+ return getResult();
+}
+
+void Platform::createGWindow(const GWindow & gw, double width, double height,
+ GObject *topCompound) {
+ ostringstream os;
+ os << gw.gwd;
+ string id = os.str();
+ windowTable.put(id, gw.gwd);
+ os.str("");
+ os << "GWindow.create(\"" << id << "\", " << width << ", " << height
+ << ", \"" << topCompound << "\")";
+ putPipe(os.str());
+ getStatus();
+}
+
+void Platform::deleteGWindow(const GWindow & gw) {
+ ostringstream os;
+ os << gw.gwd;
+ string id = os.str();
+ windowTable.remove(id);
+ os.str("");
+ os << "GWindow.delete(\"" << gw.gwd << "\")";
+ putPipe(os.str());
+}
+
+void Platform::close(const GWindow & gw) {
+ ostringstream os;
+ os << "GWindow.close(\"" << gw.gwd << "\")";
+ putPipe(os.str());
+}
+
+void Platform::requestFocus(const GWindow & gw) {
+ ostringstream os;
+ os << "GWindow.requestFocus(\"" << gw.gwd << "\")";
+ putPipe(os.str());
+}
+
+void Platform::clear(const GWindow & gw) {
+ ostringstream os;
+ os << "GWindow.clear(\"" << gw.gwd << "\")";
+ putPipe(os.str());
+}
+
+void Platform::repaint(const GWindow & gw) {
+ ostringstream os;
+ os << "GWindow.repaint(\"" << gw.gwd << "\")";
+ putPipe(os.str());
+}
+
+void Platform::setVisible(const GWindow&, bool) {
+// ostringstream os;
+// os << boolalpha << "GWindow.setVisible(\"" << gw.gwd << "\", "
+// << flag << ")";
+// putPipe(os.str());
+}
+
+void Platform::setWindowTitle(const GWindow & gw, string title) {
+ ostringstream os;
+ os << "GWindow.setTitle(\"" << gw.gwd << "\", ";
+ writeQuotedString(os, title);
+ os << ")";
+ putPipe(os.str());
+}
+
+double Platform::getScreenWidth() {
+ putPipe("GWindow.getScreenWidth()");
+ return stringToReal(getResult());
+}
+
+double Platform::getScreenHeight() {
+ putPipe("GWindow.getScreenHeight()");
+ return stringToReal(getResult());
+}
+
+void Platform::pause(double milliseconds) {
+ ostringstream os;
+ os << "GTimer.pause(" << milliseconds << ")";
+ putPipe(os.str());
+ getStatus();
+}
+
+void Platform::createTimer(const GTimer & timer, double delay) {
+ ostringstream os;
+ os << timer.gtd;
+ string id = os.str();
+ timerTable.put(id, timer.gtd);
+ os.str("");
+ os << "GTimer.create(\"" << id << "\", " << delay << ")";
+ putPipe(os.str());
+}
+
+void Platform::deleteTimer(const GTimer & timer) {
+ ostringstream os;
+ os << timer.gtd;
+ string id = os.str();
+ timerTable.remove(id);
+ os.str("");
+ os << "GTimer.deleteTimer(\"" << id << "\")";
+ putPipe(os.str());
+}
+
+void Platform::startTimer(const GTimer & timer) {
+ ostringstream os;
+ os << "GTimer.startTimer(\"" << timer.gtd << "\")";
+ putPipe(os.str());
+}
+
+void Platform::stopTimer(const GTimer & timer) {
+ ostringstream os;
+ os << "GTimer.stopTimer(\"" << timer.gtd << "\")";
+ putPipe(os.str());
+}
+
+void Platform::createSound(Sound *sound, string filename) {
+ ostringstream os;
+ os << "Sound.create(\"" << sound << "\", ";
+ writeQuotedString(os, filename);
+ os << ")";
+ putPipe(os.str());
+ getStatus();
+}
+
+void Platform::deleteSound(Sound *sound) {
+ ostringstream os;
+ os << "Sound.delete(\"" << sound << "\")";
+ putPipe(os.str());
+}
+
+void Platform::playSound(Sound *sound) {
+ ostringstream os;
+ os << "Sound.play(\"" << sound << "\")";
+ putPipe(os.str());
+}
+
+void Platform::deleteGObject(GObject *gobj) {
+ ostringstream os;
+ os << "GObject.delete(\"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::add(GObject *compound, GObject *gobj) {
+ ostringstream os;
+ os << "GCompound.add(\"" << compound << "\", \"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::remove(GObject *gobj) {
+ ostringstream os;
+ os << "GObject.remove(\"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::setRegionAlignment(const GWindow & gw, string region,
+ string align) {
+ ostringstream os;
+ os << "GWindow.setRegionAlignment(\"" << gw.gwd << "\", \"" << region
+ << "\", \"" << align << "\")";
+ putPipe(os.str());
+}
+
+void Platform::addToRegion(const GWindow & gw, GObject *gobj, string region) {
+ ostringstream os;
+ os << "GWindow.addToRegion(\"" << gw.gwd << "\", \"" << gobj << "\", \""
+ << region << "\")";
+ putPipe(os.str());
+}
+
+void Platform::removeFromRegion(const GWindow & gw, GObject *gobj,
+ string region) {
+ ostringstream os;
+ os << "GWindow.removeFromRegion(\"" << gw.gwd << "\", \""
+ << gobj << "\", \"" << region << "\")";
+ putPipe(os.str());
+}
+
+void Platform::sendForward(GObject *gobj) {
+ ostringstream os;
+ os << "GObject.sendForward(\"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::sendToFront(GObject *gobj) {
+ ostringstream os;
+ os << "GObject.sendToFront(\"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::sendBackward(GObject *gobj) {
+ ostringstream os;
+ os << "GObject.sendBackward(\"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::sendToBack(GObject *gobj) {
+ ostringstream os;
+ os << "GObject.sendToBack(\"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::setVisible(GObject *gobj, bool flag) {
+ ostringstream os;
+ os << boolalpha << "GObject.setVisible(\"" << gobj << "\", " << flag << ")";
+ putPipe(os.str());
+}
+
+void Platform::setColor(GObject *gobj, string color) {
+ ostringstream os;
+ os << "GObject.setColor(\"" << gobj << "\", \"" << color << "\")";
+ putPipe(os.str());
+}
+
+void Platform::scale(GObject *gobj, double sx, double sy) {
+ ostringstream os;
+ os << "GObject.scale(\"" << gobj << "\", " << sx << ", " << sy << ")";
+ putPipe(os.str());
+}
+
+void Platform::rotate(GObject *gobj, double theta) {
+ ostringstream os;
+ os << "GObject.rotate(\"" << gobj << "\", " << theta << ")";
+ putPipe(os.str());
+}
+
+// Move this computation into gobjects.cpp
+
+bool Platform::contains(const GObject *gobj, double x, double y) {
+ ostringstream os;
+ os << "GObject.contains(\"" << gobj << "\", " << x << ", " << y << ")";
+ putPipe(os.str());
+ return getResult() == "true";
+}
+
+// Move this computation into gobjects.cpp
+
+GRectangle Platform::getBounds(const GObject *gobj) {
+ ostringstream os;
+ os << "GObject.getBounds(\"" << gobj << "\")";
+ putPipe(os.str());
+ string result = getResult();
+ if (!startsWith(result, "GRectangle(")) error(result);
+ return scanRectangle(result);
+}
+
+void Platform::setLineWidth(GObject *gobj, double lineWidth) {
+ ostringstream os;
+ os << "GObject.setLineWidth(\"" << gobj << "\", " << lineWidth << ")";
+ putPipe(os.str());
+}
+
+void Platform::setLocation(GObject *gobj, double x, double y) {
+ ostringstream os;
+ os << "GObject.setLocation(\"" << gobj << "\", " << x << ", " << y << ")";
+ putPipe(os.str());
+}
+
+void Platform::setSize(GObject *gobj, double width, double height) {
+ ostringstream os;
+ os << "GObject.setSize(\"" << gobj << "\", " << width << ", "
+ << height << ")";
+ putPipe(os.str());
+}
+
+void Platform::setFrameRectangle(GObject *gobj, double x, double y,
+ double width, double height) {
+ ostringstream os;
+ os << "GArc.setFrameRectangle(\"" << gobj << "\", "
+ << x << ", " << y << ", "
+ << width << ", " << height << ")";
+ putPipe(os.str());
+}
+
+void Platform::draw(const GWindow & gw, const GObject *gobj) {
+ ostringstream os;
+ os << "GWindow.draw(\"" << gw.gwd << "\", \"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::setFilled(GObject *gobj, bool flag) {
+ ostringstream os;
+ os << boolalpha << "GObject.setFilled(\"" << gobj << "\", " << flag << ")";
+ putPipe(os.str());
+}
+
+void Platform::setFillColor(GObject *gobj, string color) {
+ ostringstream os;
+ os << "GObject.setFillColor(\"" << gobj << "\", \"" << color << "\")";
+ putPipe(os.str());
+}
+
+void Platform::createGRect(GObject *gobj, double width, double height) {
+ ostringstream os;
+ os << "GRect.create(\"" << gobj << "\", " << width << ", "
+ << height << ")";
+ putPipe(os.str());
+}
+
+void Platform::createGRoundRect(GObject *gobj, double width, double height,
+ double corner) {
+ ostringstream os;
+ os << "GRoundRect.create(\"" << gobj << "\", " << width << ", " << height
+ << ", " << corner << ")";
+ putPipe(os.str());
+}
+
+void Platform::createG3DRect(GObject *gobj, double width, double height,
+ bool raised) {
+ ostringstream os;
+ os << boolalpha << "G3DRect.create(\"" << gobj << "\", "
+ << width << ", " << height << ", " << raised << ")";
+ putPipe(os.str());
+}
+
+void Platform::setRaised(GObject *gobj, bool raised) {
+ ostringstream os;
+ os << boolalpha << "G3DRect.setRaised(\"" << gobj << "\", "
+ << raised << ")";
+ putPipe(os.str());
+}
+
+void Platform::createGLabel(GObject *gobj, string label) {
+ ostringstream os;
+ // *** BUGBUG: must escape quotation marks in label string (Marty)
+ os << "GLabel.create(\"" << gobj << "\", ";
+ writeQuotedString(os, label);
+ os << ")";
+ putPipe(os.str());
+}
+
+void Platform::createGLine(GObject *gobj, double x1, double y1,
+ double x2, double y2) {
+ ostringstream os;
+ os << "GLine.create(\"" << gobj << "\", " << x1 << ", " << y1
+ << ", " << x2 << ", " << y2 << ")";
+ putPipe(os.str());
+}
+
+void Platform::setStartPoint(GObject *gobj, double x, double y) {
+ ostringstream os;
+ os << "GLine.setStartPoint(\"" << gobj << "\", " << x << ", " << y << ")";
+ putPipe(os.str());
+}
+
+void Platform::setEndPoint(GObject *gobj, double x, double y) {
+ ostringstream os;
+ os << "GLine.setEndPoint(\"" << gobj << "\", " << x << ", " << y << ")";
+ putPipe(os.str());
+}
+
+void Platform::createGArc(GObject *gobj, double width, double height,
+ double start, double sweep) {
+ ostringstream os;
+ os << "GArc.create(\"" << gobj << "\", " << width << ", " << height
+ << ", " << start << ", " << sweep << ")";
+ putPipe(os.str());
+}
+
+void Platform::setStartAngle(GObject *gobj, double angle) {
+ ostringstream os;
+ os << "GArc.setStartAngle(\"" << gobj << "\", " << angle << ")";
+ putPipe(os.str());
+}
+
+void Platform::setSweepAngle(GObject *gobj, double angle) {
+ ostringstream os;
+ os << "GArc.setSweepAngle(\"" << gobj << "\", " << angle << ")";
+ putPipe(os.str());
+}
+
+GDimension Platform::createGImage(GObject *gobj, string filename) {
+ ostringstream os;
+ os << "GImage.create(\"" << gobj << "\", \"" << filename << "\")";
+ putPipe(os.str());
+ string result = getResult();
+ if (!startsWith(result, "GDimension(")) error(result);
+ return scanDimension(result);
+}
+
+void Platform::createGPolygon(GObject *gobj) {
+ ostringstream os;
+ os << "GPolygon.create(\"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::addVertex(GObject *gobj, double x, double y) {
+ ostringstream os;
+ os << "GPolygon.addVertex(\"" << gobj << "\", " << x << ", " << y << ")";
+ putPipe(os.str());
+}
+
+void Platform::createGOval(GObject *gobj, double width, double height) {
+ ostringstream os;
+ os << "GOval.create(\"" << gobj << "\", " << width << ", "
+ << height << ")";
+ putPipe(os.str());
+}
+
+void Platform::setActionCommand(GObject *gobj, string cmd) {
+ ostringstream os;
+ os << "GInteractor.setActionCommand(\"" << gobj << "\", ";
+ writeQuotedString(os, cmd);
+ os << ")";
+ putPipe(os.str());
+}
+
+GDimension Platform::getSize(GObject *gobj) {
+ ostringstream os;
+ os << "GInteractor.getSize(\"" << gobj << "\")";
+ putPipe(os.str());
+ return scanDimension(getResult());
+}
+
+void Platform::createGButton(GObject *gobj, string label) {
+ ostringstream os;
+ os << gobj;
+ sourceTable.put(os.str(), gobj);
+ os.str("");
+ os << "GButton.create(\"" << gobj << "\", ";
+ writeQuotedString(os, label);
+ os << ")";
+ putPipe(os.str());
+}
+
+void Platform::createGCheckBox(GObject *gobj, string label) {
+ ostringstream os;
+ os << gobj;
+ sourceTable.put(os.str(), gobj);
+ os.str("");
+ os << "GCheckBox.create(\"" << gobj << "\", ";
+ writeQuotedString(os, label);
+ os << ")";
+ putPipe(os.str());
+}
+
+bool Platform::isSelected(GObject *gobj) {
+ ostringstream os;
+ os << "GCheckBox.isSelected(\"" << gobj << "\")";
+ putPipe(os.str());
+ return getResult() == "true";
+}
+
+void Platform::setSelected(GObject *gobj, bool state) {
+ ostringstream os;
+ os << boolalpha << "GCheckBox.setSelected(\"" << gobj << "\", "
+ << state << ")";
+ putPipe(os.str());
+}
+
+void Platform::createGSlider(GObject *gobj, int min, int max, int value) {
+ ostringstream os;
+ os << gobj;
+ sourceTable.put(os.str(), gobj);
+ os.str("");
+ os << "GSlider.create(\"" << gobj << "\", " << min << ", " << max
+ << ", " << value << ")";
+ putPipe(os.str());
+}
+
+int Platform::getValue(GObject *gobj) {
+ ostringstream os;
+ os << "GSlider.getValue(\"" << gobj << "\")";
+ putPipe(os.str());
+ return stringToInteger(getResult());
+}
+
+void Platform::setValue(GObject *gobj, int value) {
+ ostringstream os;
+ os << "GSlider.setValue(\"" << gobj << "\", " << value << ")";
+ putPipe(os.str());
+}
+
+void Platform::createGTextField(GObject *gobj, int nChars) {
+ ostringstream os;
+ os << gobj;
+ sourceTable.put(os.str(), gobj);
+ os.str("");
+ os << "GTextField.create(\"" << gobj << "\", " << nChars << ")";
+ putPipe(os.str());
+}
+
+string Platform::getText(GObject *gobj) {
+ ostringstream os;
+ os << "GTextField.getText(\"" << gobj << "\")";
+ putPipe(os.str());
+ return getResult();
+}
+
+void Platform::setText(GObject *gobj, string str) {
+ ostringstream os;
+ os << "GTextField.setText(\"" << gobj << "\", ";
+ writeQuotedString(os, str);
+ os << ")";
+ putPipe(os.str());
+}
+
+void Platform::createGChooser(GObject *gobj) {
+ ostringstream os;
+ os << gobj;
+ sourceTable.put(os.str(), gobj);
+ os.str("");
+ os << "GChooser.create(\"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::addItem(GObject *gobj, string item) {
+ ostringstream os;
+ os << "GChooser.addItem(\"" << gobj << "\", ";
+ writeQuotedString(os, item);
+ os << ")";
+ putPipe(os.str());
+}
+
+string Platform::getSelectedItem(GObject *gobj) {
+ ostringstream os;
+ os << "GChooser.getSelectedItem(\"" << gobj << "\")";
+ putPipe(os.str());
+ return getResult();
+}
+
+void Platform::setSelectedItem(GObject *gobj, string item) {
+ ostringstream os;
+ os << "GChooser.setSelectedItem(\"" << gobj << "\", ";
+ writeQuotedString(os, item);
+ os << ")";
+ putPipe(os.str());
+}
+
+void Platform::createGCompound(GObject *gobj) {
+ ostringstream os;
+ os << "GCompound.create(\"" << gobj << "\")";
+ putPipe(os.str());
+}
+
+void Platform::setFont(GObject *gobj, string font) {
+ ostringstream os;
+ os << "GLabel.setFont(\"" << gobj << "\", \"" << font << "\")";
+ putPipe(os.str());
+}
+
+void Platform::setLabel(GObject *gobj, string str) {
+ ostringstream os;
+ os << "GLabel.setLabel(\"" << gobj << "\", ";
+ writeQuotedString(os, str);
+ os << ")";
+ putPipe(os.str());
+}
+
+double Platform::getFontAscent(const GObject *gobj) {
+ ostringstream os;
+ os << "GLabel.getFontAscent(\"" << gobj << "\")";
+ putPipe(os.str());
+ return stringToReal(getResult());
+}
+
+double Platform::getFontDescent(const GObject *gobj) {
+ ostringstream os;
+ os << "GLabel.getFontDescent(\"" << gobj << "\")";
+ putPipe(os.str());
+ return stringToReal(getResult());
+}
+
+GDimension Platform::getGLabelSize(const GObject *gobj) {
+ ostringstream os;
+ os << "GLabel.getGLabelSize(\"" << gobj << "\")";
+ putPipe(os.str());
+ return scanDimension(getResult());
+}
+
+GEvent Platform::getNextEvent(int mask) {
+ if (eventQueue.isEmpty()) {
+ putPipe("GEvent.getNextEvent(" + integerToString(mask) + ")");
+ getResult();
+ if (eventQueue.isEmpty()) return GEvent();
+ }
+ return eventQueue.dequeue();
+}
+
+GEvent Platform::waitForEvent(int mask) {
+ while (eventQueue.isEmpty()) {
+ putPipe("GEvent.waitForEvent(" + integerToString(mask) + ")");
+ getResult();
+ }
+ return eventQueue.dequeue();
+}
+
+void Platform::exitGraphics() {
+ putPipe("GWindow.exitGraphics()");
+ exit(0);
+}
+
+Platform *getPlatform() {
+ static Platform gp;
+ return &gp;
+}
+
+#ifdef _WIN32
+
+/* Windows implementation of interface to Java back end */
+
+int startupMain(int argc, char **argv) {
+ extern int Main(int argc, char **argv);
+ programName = getRoot(getTail(argv[0]));
+ initPipe();
+#ifndef PLAIN_TEXT_CONSOLE
+ cin_old_buf = cin.rdbuf();
+ cout_old_buf = cout.rdbuf();
+ cinout_new_buf = new ConsoleStreambuf();
+ cin.rdbuf(cinout_new_buf);
+ cout.rdbuf(cinout_new_buf);
+ ShowWindow(GetConsoleWindow(), SW_HIDE);
+#endif
+ return Main(argc, argv);
+}
+
+static void initPipe() {
+ SECURITY_ATTRIBUTES attr;
+ attr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ attr.bInheritHandle = true;
+ attr.lpSecurityDescriptor = NULL;
+ if (!CreatePipe(&rdFromJBE, &wrFromJBE, &attr, 0)) {
+ error("Can't create fromJBE");
+ }
+ if (!SetHandleInformation(rdFromJBE, HANDLE_FLAG_INHERIT, 0)) {
+ error("SetHandleInformation failed for fromJBE");
+ }
+ if (!CreatePipe(&rdToJBE, &wrToJBE, &attr, 0)) {
+ error("Can't create toJBE");
+ }
+ if (!SetHandleInformation(wrToJBE, HANDLE_FLAG_INHERIT, 0)) {
+ error("SetHandleInformation failed for toJBE");
+ }
+ string cmd = "java -jar spl.jar " + programName;
+ int n = cmd.length();
+ char *cmdLine = new char[n + 1];
+ for (int i = 0; i < n; i++) {
+ cmdLine[i] = cmd[i];
+ }
+ cmdLine[n] = '\0';
+ PROCESS_INFORMATION pInfo;
+ memset(&pInfo, 0, sizeof(PROCESS_INFORMATION));
+ STARTUPINFOA sInfo;
+ memset(&sInfo, 0, sizeof(STARTUPINFOA));
+ sInfo.cb = sizeof(STARTUPINFOA);
+ sInfo.dwFlags = STARTF_USESTDHANDLES;
+ sInfo.hStdInput = rdToJBE;
+ sInfo.hStdOutput = wrFromJBE;
+ sInfo.hStdError = wrFromJBE;
+ int ok = CreateProcessA(NULL, cmdLine, NULL, NULL, true, CREATE_NO_WINDOW,
+ NULL, NULL, &sInfo, &pInfo);
+ if (!ok) {
+ DWORD err = GetLastError();
+ cerr << endl;
+ cerr << "ERROR: Stanford C++ library was unable to connect" << endl;
+ cerr << " to its Java back-end to launch 'spl.jar'." << endl;
+ cerr << " Please check your Java installation and make sure" << endl;
+ cerr << " that spl.jar is properly attached to your project." << endl;
+ cerr << endl;
+ cerr << err << endl;
+ } else {
+ CloseHandle(pInfo.hProcess);
+ CloseHandle(pInfo.hThread);
+ }
+}
+
+static void putPipe(string line) {
+ DWORD nch;
+ WriteFile(wrToJBE, line.c_str(), line.length(), &nch, NULL);
+ WriteFile(wrToJBE, "\n", 1, &nch, NULL);
+ FlushFileBuffers(wrToJBE);
+}
+
+static string getPipe() {
+ string line = "";
+ DWORD nch;
+ while (true) {
+ char ch;
+ ReadFile(rdFromJBE, &ch, 1, &nch, NULL);
+ if (ch == '\n' || ch == '\r') break;
+ line += ch;
+ }
+
+ // cerr << "getPipe(): \"" << line << "\"" << endl;
+ return line;
+}
+
+#else
+
+/* Linux/Mac implementation of interface to Java back end */
+
+static void scanOptions() {
+ char *home = getenv("HOME");
+ if (home != NULL) {
+ string filename = string() + home + "/.spl";
+ ifstream infile(filename.c_str());
+ if (!infile.fail()) {
+ string line;
+ while (getline(infile, line)) {
+ size_t equals = line.find('=');
+ if (equals != string::npos) {
+ string key = line.substr(0, equals);
+ string value = line.substr(equals + 1);
+ optionTable.put(key, value);
+ }
+ }
+ infile.close();
+ }
+ }
+}
+
+static string getOption(string key) {
+ char *str = getenv(key.c_str());
+ if (str != NULL) return string(str);
+ return optionTable.get(key);
+}
+
+int startupMain(int argc, char **argv) {
+ extern int Main(int argc, char **argv);
+ string arg0 = argv[0];
+ programName = getRoot(getTail(arg0));
+ size_t ax = arg0.find(".app/Contents/");
+ if (ax != string::npos) {
+ while (ax > 0 && arg0[ax] != '/') {
+ ax--;
+ }
+ if (ax > 0) {
+ string cwd = arg0.substr(0, ax);
+ chdir(cwd.c_str());
+ }
+ }
+ char *noConsoleFlag = getenv("NOCONSOLE");
+ if (noConsoleFlag != NULL && startsWith(string(noConsoleFlag), "t")) {
+ return Main(argc, argv);
+ }
+ scanOptions();
+ initPipe();
+#ifndef PLAIN_TEXT_CONSOLE
+ cin_old_buf = cin.rdbuf();
+ cout_old_buf = cout.rdbuf();
+ cinout_new_buf = new ConsoleStreambuf();
+ cin.rdbuf(cinout_new_buf);
+ cout.rdbuf(cinout_new_buf);
+ string font = getOption("CPPFONT");
+ if (font != "") setConsoleFont(font);
+#endif
+ return Main(argc, argv);
+}
+
+static void initPipe() {
+ char *trace = getenv("JBETRACE");
+ logfile.open("/dev/tty");
+ tracePipe = trace != NULL && startsWith(toLowerCase(trace), "t");
+ int toJBE[2], fromJBE[2];
+ pipe(toJBE);
+ pipe(fromJBE);
+ int child = fork();
+ if (child == 0) {
+ dup2(toJBE[0], 0);
+ close(toJBE[0]);
+ close(toJBE[1]);
+ dup2(fromJBE[1], 1);
+ close(fromJBE[0]);
+ close(fromJBE[1]);
+#ifdef __APPLE__
+ string option = "-Xdock:name=" + programName;
+ execlp("java", "java", option.c_str(), "-jar", "spl.jar",
+ programName.c_str(), NULL);
+#else
+ execlp("java", "java", "-jar", "spl.jar", programName.c_str(), NULL);
+#endif
+ cerr << endl;
+ cerr << "ERROR: Stanford C++ library was unable to connect" << endl;
+ cerr << " to its Java back-end to launch 'spl.jar'." << endl;
+ cerr << " Please check your Java installation and make sure" << endl;
+ cerr << " that spl.jar is properly attached to your project." << endl;
+ cerr << endl;
+ throw new ErrorException("Could not exec spl.jar");
+ } else {
+ pin = fromJBE[0];
+ pout = toJBE[1];
+ close(fromJBE[1]);
+ close(toJBE[0]);
+ }
+}
+
+static void putPipe(string line) {
+ write(pout, line.c_str(), line.length());
+ write(pout, "\n", 1);
+ if (tracePipe) logfile << "-> " << line << endl;
+}
+
+static string getPipe() {
+ string line = "";
+ while (true) {
+ char ch;
+ read(pin, &ch, 1);
+ if (ch == '\n') break;
+ line += ch;
+ }
+ if (tracePipe) logfile << "<- " << line << endl;
+ return line;
+}
+
+#endif
+
+static string getResult() {
+ while (true) {
+ string line = getPipe();
+ bool result = startsWith(line, "result:");
+ bool event = startsWith(line, "event:");
+ bool hasACMException = line.find("acm.util.ErrorException") != string::npos;
+ bool hasException = line.find("xception") != string::npos;
+
+ // *** added by Marty: if there is a back-end error, display it
+ if (((result || event) && hasACMException) || (!result && !event && hasException)) {
+ cerr << "ERROR emitted from Stanford Java back-end process:"
+ << endl << line << endl;
+ throw new ErrorException(line.substr(result ? 7 : 6));
+ } else if (startsWith(line, "result:")) {
+ return line.substr(7);
+ } else if (startsWith(line, "event:")) {
+ eventQueue.enqueue(parseEvent(line.substr(6)));
+ } else {
+ if (line.find("\tat") == 0) {
+ // part of a Java exception stack trace, so echo it
+ cerr << line << endl;
+ }
+ }
+ }
+}
+
+static void getStatus() {
+ string result = getResult();
+ if (result != "ok") error(result);
+}
+
+static GEvent parseEvent(string line) {
+ TokenScanner scanner(line);
+ scanner.ignoreWhitespace();
+ scanner.scanNumbers();
+ scanner.scanStrings();
+ string name = scanner.nextToken();
+ if (name == "mousePressed") {
+ return parseMouseEvent(scanner, MOUSE_PRESSED);
+ } else if (name == "mouseReleased") {
+ return parseMouseEvent(scanner, MOUSE_RELEASED);
+ } else if (name == "mouseClicked") {
+ return parseMouseEvent(scanner, MOUSE_CLICKED);
+ } else if (name == "mouseMoved") {
+ return parseMouseEvent(scanner, MOUSE_MOVED);
+ } else if (name == "mouseDragged") {
+ return parseMouseEvent(scanner, MOUSE_DRAGGED);
+ } else if (name == "keyPressed") {
+ return parseKeyEvent(scanner, KEY_PRESSED);
+ } else if (name == "keyReleased") {
+ return parseKeyEvent(scanner, KEY_RELEASED);
+ } else if (name == "keyTyped") {
+ return parseKeyEvent(scanner, KEY_TYPED);
+ } else if (name == "actionPerformed") {
+ return parseActionEvent(scanner, ACTION_PERFORMED);
+ } else if (name == "timerTicked") {
+ return parseTimerEvent(scanner, TIMER_TICKED);
+ } else if (name == "windowClosed") {
+ GWindowEvent e = parseWindowEvent(scanner, WINDOW_CLOSED);
+ e.getGWindow().setVisible(false);
+ e.getGWindow().close();
+ return e;
+ } else if (name == "windowResized") {
+ return parseWindowEvent(scanner, WINDOW_RESIZED);
+ } else if (name == "lastWindowClosed") {
+ exit(0);
+ } else if (name == "lastWindowGWindow_closed") {
+ exit(0);
+ } else {
+ /* Ignore for now */
+ }
+ return GEvent();
+}
+
+static GEvent parseMouseEvent(TokenScanner & scanner, EventType type) {
+ scanner.verifyToken("(");
+ string id = scanner.getStringValue(scanner.nextToken());
+ scanner.verifyToken(",");
+ double time = scanDouble(scanner);
+ scanner.verifyToken(",");
+ int modifiers = scanInt(scanner);
+ scanner.verifyToken(",");
+ double x = scanDouble(scanner);
+ scanner.verifyToken(",");
+ double y = scanDouble(scanner);
+ scanner.verifyToken(")");
+ GMouseEvent e(type, GWindow(windowTable.get(id)), x, y);
+ e.setEventTime(time);
+ e.setModifiers(modifiers);
+ return e;
+}
+
+static GEvent parseKeyEvent(TokenScanner & scanner, EventType type) {
+ scanner.verifyToken("(");
+ string id = scanner.getStringValue(scanner.nextToken());
+ scanner.verifyToken(",");
+ double time = scanDouble(scanner);
+ scanner.verifyToken(",");
+ int modifiers = scanInt(scanner);
+ scanner.verifyToken(",");
+ int keyChar = scanInt(scanner);
+ scanner.verifyToken(",");
+ int keyCode = scanInt(scanner);
+ scanner.verifyToken(")");
+ GKeyEvent e(type, GWindow(windowTable.get(id)), char(keyChar), keyCode);
+ e.setEventTime(time);
+ e.setModifiers(modifiers);
+ return e;
+}
+
+static GEvent parseTimerEvent(TokenScanner & scanner, EventType type) {
+ scanner.verifyToken("(");
+ string id = scanner.getStringValue(scanner.nextToken());
+ scanner.verifyToken(",");
+ double time = scanDouble(scanner);
+ scanner.verifyToken(")");
+ GTimerEvent e(type, GTimer(timerTable.get(id)));
+ e.setEventTime(time);
+ return e;
+}
+
+static GEvent parseWindowEvent(TokenScanner & scanner, EventType type) {
+ scanner.verifyToken("(");
+ string id = scanner.getStringValue(scanner.nextToken());
+ scanner.verifyToken(",");
+ double time = scanDouble(scanner);
+ scanner.verifyToken(")");
+ GWindowEvent e(type, GWindow(windowTable.get(id)));
+ e.setEventTime(time);
+ return e;
+}
+
+static GEvent parseActionEvent(TokenScanner & scanner, EventType type) {
+ scanner.verifyToken("(");
+ string id = scanner.getStringValue(scanner.nextToken());
+ scanner.verifyToken(",");
+ string action = scanner.getStringValue(scanner.nextToken());
+ scanner.verifyToken(",");
+ double time = scanDouble(scanner);
+ scanner.verifyToken(")");
+ GActionEvent e(type, sourceTable.get(id), action);
+ e.setEventTime(time);
+ return e;
+}
+
+/* Console code */
+
+void Platform::clearConsole() {
+ putPipe("JBEConsole.clear()");
+}
+
+void Platform::setConsoleFont(const string & font) {
+ ostringstream os;
+ os << "JBEConsole.setFont(\"" << font << "\")";
+ putPipe(os.str());
+}
+
+void Platform::setConsoleSize(double width, double height) {
+ ostringstream os;
+ os << "JBEConsole.setSize(" << width << ", " << height << ")";
+ putPipe(os.str());
+}
+
+static string getLineConsole() {
+ putPipe("JBEConsole.getLine()");
+ string result = getResult();
+ echoConsole(result + "\n"); // wrong for multiple inputs on one line
+ return result;
+}
+
+static void putConsole(const string & str) {
+ ostringstream os;
+ os << "JBEConsole.print(";
+ writeQuotedString(os, str);
+ os << ")";
+ putPipe(os.str());
+ echoConsole(str);
+}
+
+static void echoConsole(const string & str) {
+ if (getConsoleEcho()) {
+ // write to the standard cout console for output copy/pasting
+ cin.rdbuf(cin_old_buf);
+ cout.rdbuf(cout_old_buf);
+ cout << str;
+ cout.flush();
+ cin.rdbuf(cinout_new_buf);
+ cout.rdbuf(cinout_new_buf);
+ }
+ fileLogConsole(str);
+}
+
+static void fileLogConsole(const string & str) {
+ string consoleLogFile = getConsoleLogFile();
+ if (consoleLogFile.length() > 0) {
+ // A bit inefficient; opens/writes/closes the file on each print
+ // statement. But this enables fine-grained control and changing
+ // the log file in mid-execution with minimal code base change
+ ofstream outfile;
+ outfile.open(consoleLogFile.c_str(), fstream::out | fstream::app);
+ outfile << str;
+ outfile.flush();
+ outfile.close();
+ }
+}
+
+static void endLineConsole() {
+ putPipe("JBEConsole.println()");
+ echoConsole("\n");
+}
+
+static int scanInt(TokenScanner & scanner) {
+ string token = scanner.nextToken();
+ if (token == "-") token += scanner.nextToken();
+ return stringToInteger(token);
+}
+
+static double scanDouble(TokenScanner & scanner) {
+ string token = scanner.nextToken();
+ if (token == "-") token += scanner.nextToken();
+ return stringToReal(token);
+}
+
+static GDimension scanDimension(const string & str) {
+ TokenScanner scanner(str);
+ scanner.scanNumbers();
+ scanner.ignoreWhitespace();
+ scanner.verifyToken("GDimension");
+ scanner.verifyToken("(");
+ double width = scanDouble(scanner);
+ scanner.verifyToken(",");
+ double height = scanDouble(scanner);
+ scanner.verifyToken(")");
+ return GDimension(width, height);
+}
+
+static GRectangle scanRectangle(const string & str) {
+ TokenScanner scanner(str);
+ scanner.scanNumbers();
+ scanner.ignoreWhitespace();
+ scanner.verifyToken("GRectangle");
+ scanner.verifyToken("(");
+ double x = scanDouble(scanner);
+ scanner.verifyToken(",");
+ double y = scanDouble(scanner);
+ scanner.verifyToken(",");
+ double width = scanDouble(scanner);
+ scanner.verifyToken(",");
+ double height = scanDouble(scanner);
+ scanner.verifyToken(")");
+ return GRectangle(x, y, width, height);
+}
diff --git a/labb8/lib/StanfordCPPLib/platform.h b/labb8/lib/StanfordCPPLib/platform.h
new file mode 100755
index 0000000..85f916f
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/platform.h
@@ -0,0 +1,134 @@
+/*
+ * File: platform.h
+ * ----------------
+ * This file defines the <code>Platform</code> class, which encapsulates
+ * the platform-specific parts of the StanfordCPPLib package. This file is
+ * logically part of the implementation and is not interesting to clients.
+ */
+
+#ifndef _platform_h
+#define _platform_h
+
+#include <string>
+#include <vector>
+#include "gevents.h"
+#include "gwindow.h"
+#include "sound.h"
+
+class Platform {
+private:
+ Platform();
+ friend Platform *getPlatform();
+
+public:
+ virtual ~Platform();
+ void clearConsole();
+ void setConsoleFont(const std::string & font);
+ void setConsoleSize(double width, double height);
+ bool fileExists(std::string filename);
+ bool isFile(std::string filename);
+ bool isSymbolicLink(std::string filename);
+ bool isDirectory(std::string filename);
+ void setCurrentDirectory(std::string path);
+ std::string getCurrentDirectory();
+ void createDirectory(std::string path);
+ std::string getDirectoryPathSeparator();
+ std::string getSearchPathSeparator();
+ std::string expandPathname(std::string filename);
+ void listDirectory(std::string path, vector<std::string> & list);
+ std::string openFileDialog(std::string title, std::string mode,
+ std::string path);
+ void createGWindow(const GWindow & gw, double width, double height,
+ GObject *topCompound);
+ void deleteGWindow(const GWindow & gw);
+ void close(const GWindow & gw);
+ void requestFocus(const GWindow & gw);
+ void clear(const GWindow & gw);
+ void repaint(const GWindow & gw);
+ void setVisible(const GWindow & gw, bool flag);
+ void setResizable(const GWindow & gw, bool flag);
+ void setWindowTitle(const GWindow & gw, std::string title);
+ void setRegionAlignment(const GWindow & gw, std::string region,
+ std::string align);
+ void addToRegion(const GWindow & gw, GObject *gobj, std::string region);
+ void removeFromRegion(const GWindow & gw, GObject *gobj,
+ std::string region);
+ void pause(double milliseconds);
+ double getScreenWidth();
+ double getScreenHeight();
+ GEvent waitForEvent(int mask);
+ GEvent getNextEvent(int mask);
+ void exitGraphics();
+ void createTimer(const GTimer & timer, double delay);
+ void deleteTimer(const GTimer & timer);
+ void startTimer(const GTimer & timer);
+ void stopTimer(const GTimer & timer);
+ void createSound(Sound *sound, std::string filename);
+ void deleteSound(Sound *sound);
+ void playSound(Sound *sound);
+ void createGRect(GObject *gobj, double width, double height);
+ void createGRoundRect(GObject *gobj, double width, double height,
+ double corner);
+ void createG3DRect(GObject *gobj, double width, double height, bool raised);
+ void setRaised(GObject *gobj, bool raised);
+ void createGOval(GObject *gobj, double width, double height);
+ void createGArc(GObject *gobj, double width, double height,
+ double start, double sweep);
+ void setStartAngle(GObject *gobj, double angle);
+ void setSweepAngle(GObject *gobj, double angle);
+ void createGLine(GObject *gobj, double x1, double y1, double x2, double y2);
+ void setStartPoint(GObject *gobj, double x, double y);
+ void setEndPoint(GObject *gobj, double x, double y);
+ void createGLabel(GObject *gobj, std::string label);
+ GDimension createGImage(GObject *gobj, std::string filename);
+ void createGPolygon(GObject *gobj);
+ void addVertex(GObject *gobj, double x, double y);
+ void setActionCommand(GObject *gobj, std::string cmd);
+ GDimension getSize(GObject *gobj);
+ void createGButton(GObject *gobj, std::string label);
+ void createGCheckBox(GObject *gobj, std::string label);
+ bool isSelected(GObject *gobj);
+ void setSelected(GObject *gobj, bool state);
+ void createGSlider(GObject *gobj, int min, int max, int value);
+ int getValue(GObject *gobj);
+ void setValue(GObject *gobj, int value);
+ void createGTextField(GObject *gobj, int nChars);
+ std::string getText(GObject *gobj);
+ void setText(GObject *gobj, std::string str);
+ void createGChooser(GObject *gobj);
+ void addItem(GObject *gobj, std::string item);
+ std::string getSelectedItem(GObject *gobj);
+ void setSelectedItem(GObject *gobj, std::string item);
+ void createGCompound(GObject *gobj);
+ void deleteGObject(GObject *gobj);
+ void add(GObject *compound, GObject *gobj);
+ void remove(GObject *gobj);
+ void sendForward(GObject *gobj);
+ void sendToFront(GObject *gobj);
+ void sendBackward(GObject *gobj);
+ void sendToBack(GObject *gobj);
+ void setVisible(GObject *gobj, bool flag);
+ void setColor(GObject *gobj, std::string color);
+ void scale(GObject *gobj, double sx, double sy);
+ void rotate(GObject *gobj, double theta);
+ GRectangle getBounds(const GObject *gobj);
+ bool contains(const GObject *gobj, double x, double y);
+ void setLineWidth(GObject *gobj, double lineWidth);
+ void setLocation(GObject *gobj, double x, double y);
+ void setSize(GObject *gobj, double width, double height);
+ void setFrameRectangle(GObject *gobj, double x, double y,
+ double width, double height);
+ void draw(const GWindow & gw, const GObject *gobj);
+ void setFilled(GObject *gobj, bool flag);
+ void setFillColor(GObject *gobj, std::string color);
+ void setFont(GObject *gobj, std::string font);
+ void setLabel(GObject *gobj, std::string str);
+ double getFontAscent(const GObject *gobj);
+ double getFontDescent(const GObject *gobj);
+ GDimension getGLabelSize(const GObject *gobj);
+
+};
+
+Platform *getPlatform();
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/point.cpp b/labb8/lib/StanfordCPPLib/point.cpp
new file mode 100755
index 0000000..351e4c8
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/point.cpp
@@ -0,0 +1,44 @@
+/*
+ * File: point.cpp
+ * ---------------
+ * This file implements the point.h interface.
+ */
+
+#include <string>
+#include "point.h"
+#include "strlib.h"
+using namespace std;
+
+Point::Point() {
+ x = 0;
+ y = 0;
+}
+
+Point::Point(int x, int y) {
+ this->x = x;
+ this->y = y;
+}
+
+int Point::getX() const {
+ return x;
+}
+
+int Point::getY() const {
+ return y;
+}
+
+string Point::toString() const {
+ return "(" + integerToString(x) + "," + integerToString(y) + ")";
+}
+
+bool Point::operator==(const Point & p2) const {
+ return (x == p2.x) && (y == p2.y);
+}
+
+bool Point::operator!=(const Point & p2) const {
+ return (x != p2.x) || (y != p2.y);
+}
+
+ostream & operator<<(ostream & os, const Point & pt) {
+ return os << pt.toString();
+}
diff --git a/labb8/lib/StanfordCPPLib/point.h b/labb8/lib/StanfordCPPLib/point.h
new file mode 100755
index 0000000..e138117
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/point.h
@@ -0,0 +1,113 @@
+/*
+ * File: point.h
+ * -------------
+ * This file exports a class representing an integer-valued <i>x</i>-<i>y</i>
+ * pair.
+ */
+
+#ifndef _point_h
+#define _point_h
+
+#include <string>
+
+/*
+ * Class: Point
+ * ------------
+ * This class represents an <i>x</i>-<i>y</i> coordinate point on a
+ * two-dimensional integer grid. If you need to work with real-valued points,
+ * you should use the <a href="gtypes.html"><code>gtypes.h</code></a>
+ * interface instead.
+ */
+
+class Point {
+
+public:
+
+/*
+ * Constructor: Point
+ * Usage: Point origin;
+ * Point pt(x, y);
+ * ----------------------
+ * Creates a <code>Point</code> object with the specified x and y coordinates.
+ * If the coordinates are not supplied, the default constructor sets these
+ * fields to 0.
+ */
+
+ Point();
+ Point(int x, int y);
+
+/*
+ * Method: getX
+ * Usage: int x = pt.getX();
+ * -------------------------
+ * Returns the <i>x</i>-coordinate of the point.
+ */
+
+ int getX() const;
+
+/*
+ * Method: getY
+ * Usage: int y = pt.getY();
+ * -------------------------
+ * Returns the <i>y</i>-coordinate of the point.
+ */
+
+ int getY() const;
+
+/*
+ * Method: toString
+ * Usage: string str = pt.toString();
+ * ----------------------------------
+ * Returns a string representation of the <code>Point</code> in the form
+ * <code>"(x, y)"</code>.
+ */
+
+ std::string toString() const;
+
+/*
+ * Friend operator: ==
+ * Usage: if (p1 == p2) ...
+ * ------------------------
+ * Returns <code>true</code> if <code>p1</code> and <code>p2</code>
+ * are the same point.
+ */
+
+ bool operator==(const Point & p2) const;
+
+/*
+ * Friend operator: !=
+ * Usage: if (p1 != p2) ...
+ * ------------------------
+ * Returns <code>true</code> if <code>p1</code> and <code>p2</code>
+ * are different.
+ */
+
+ bool operator!=(const Point & p2) const;
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+private:
+
+/* Instance variables */
+
+ int x; /* The x-coordinate of the point */
+ int y; /* The y-coordinate of the point */
+
+};
+
+/*
+ * Operator: <<
+ * Usage: cout << pt;
+ * ------------------
+ * Overloads the <code>&lt;&lt;</code> operator so that it is able
+ * to display <code>Point</code> values.
+ */
+
+std::ostream & operator<<(std::ostream & os, const Point & pt);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/pqueue.h b/labb8/lib/StanfordCPPLib/pqueue.h
new file mode 100755
index 0000000..1946797
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/pqueue.h
@@ -0,0 +1,400 @@
+/*
+ * File: pqueue.h
+ * --------------
+ * This file exports the <code>PriorityQueue</code> class, a
+ * collection in which values are processed in priority order.
+ */
+
+#ifndef _pqueue_h
+#define _pqueue_h
+
+#include "vector.h"
+
+/*
+ * Class: PriorityQueue<ValueType>
+ * -------------------------------
+ * This class models a structure called a <b><i>priority&nbsp;queue</i></b>
+ * in which values are processed in order of priority. As in conventional
+ * English usage, lower priority numbers correspond to higher effective
+ * priorities, so that a priority 1 item takes precedence over a
+ * priority 2 item.
+ */
+
+template <typename ValueType>
+class PriorityQueue {
+
+public:
+
+/*
+ * Constructor: PriorityQueue
+ * Usage: PriorityQueue<ValueType> pq;
+ * -----------------------------------
+ * Initializes a new priority queue, which is initially empty.
+ */
+
+ PriorityQueue();
+
+/*
+ * Destructor: ~PriorityQueue
+ * --------------------------
+ * Frees any heap storage associated with this priority queue.
+ */
+
+ virtual ~PriorityQueue();
+
+/*
+ * Method: size
+ * Usage: int n = pq.size();
+ * -------------------------
+ * Returns the number of values in the priority queue.
+ */
+
+ int size() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (pq.isEmpty()) ...
+ * ----------------------------
+ * Returns <code>true</code> if the priority queue contains no elements.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: clear
+ * Usage: pq.clear();
+ * ------------------
+ * Removes all elements from the priority queue.
+ */
+
+ void clear();
+
+/*
+ * Method: enqueue
+ * Usage: pq.enqueue(value, priority);
+ * -----------------------------------
+ * Adds <code>value</code> to the queue with the specified priority.
+ * Lower priority numbers correspond to higher priorities, which
+ * means that all priority 1 elements are dequeued before any
+ * priority 2 elements.
+ */
+
+ void enqueue(ValueType value, double priority);
+
+/*
+ * Method: changePriority
+ * Usage: pq.changePriority(value, newPriority);
+ * -----------------------------------
+ * Adjusts <code>value</code> in the queue to now have the specified new priority,
+ * which must be at least as urgent (lower number) than that value's previous
+ * priority in the queue.
+ * Throws an error if the element value is not present in the queue, or if the
+ * new priority passed is not at least as urgent as its current priority.
+ */
+
+void changePriority(ValueType value, double newPriority);
+
+/*
+ * Method: dequeue
+ * Usage: ValueType first = pq.dequeue();
+ * --------------------------------------
+ * Removes and returns the highest priority value. If multiple
+ * entries in the queue have the same priority, those values are
+ * dequeued in the same order in which they were enqueued.
+ */
+
+ ValueType dequeue();
+
+/*
+ * Method: peek
+ * Usage: ValueType first = pq.peek();
+ * -----------------------------------
+ * Returns the value of highest priority in the queue, without
+ * removing it.
+ */
+
+ ValueType peek() const;
+
+/*
+ * Method: peekPriority
+ * Usage: double priority = pq.peekPriority();
+ * -------------------------------------------
+ * Returns the priority of the first element in the queue, without
+ * removing it.
+ */
+
+ double peekPriority() const;
+
+/*
+ * Method: front
+ * Usage: ValueType first = pq.front();
+ * ------------------------------------
+ * Returns the first value in the queue by reference.
+ */
+
+ ValueType & front();
+
+/*
+ * Method: back
+ * Usage: ValueType last = pq.back();
+ * ----------------------------------
+ * Returns the last value in the queue by reference.
+ */
+
+ ValueType & back();
+
+/*
+ * Method: toString
+ * Usage: string str = pq.toString();
+ * ----------------------------------
+ * Converts the queue to a printable string representation.
+ */
+
+ std::string toString();
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+/*
+ * Implementation notes: PriorityQueue data structure
+ * --------------------------------------------------
+ * The PriorityQueue class is implemented using a data structure called
+ * a heap.
+ */
+
+private:
+
+/* Type used for each heap entry */
+
+ struct HeapEntry {
+ ValueType value;
+ double priority;
+ long sequence;
+ };
+
+/* Instance variables */
+
+ Vector<HeapEntry> heap;
+ long enqueueCount;
+ int backIndex;
+ int count;
+ int capacity;
+
+/* Private function prototypes */
+
+ void enqueueHeap(ValueType & value, double priority);
+ ValueType dequeueHeap();
+ bool takesPriority(int i1, int i2);
+ void swapHeapEntries(int i1, int i2);
+
+};
+
+extern void error(std::string msg);
+
+template <typename ValueType>
+PriorityQueue<ValueType>::PriorityQueue() {
+ clear();
+}
+
+/*
+ * Implementation notes: ~PriorityQueue destructor
+ * -----------------------------------------------
+ * All of the dynamic memory is allocated in the Vector class,
+ * so no work is required at this level.
+ */
+
+template <typename ValueType>
+PriorityQueue<ValueType>::~PriorityQueue() {
+ /* Empty */
+}
+
+template <typename ValueType>
+int PriorityQueue<ValueType>::size() const {
+ return count;
+}
+
+template <typename ValueType>
+bool PriorityQueue<ValueType>::isEmpty() const {
+ return count == 0;
+}
+
+template <typename ValueType>
+void PriorityQueue<ValueType>::clear() {
+ heap.clear();
+ count = 0;
+}
+
+template <typename ValueType>
+void PriorityQueue<ValueType>::enqueue(ValueType value, double priority) {
+ if (count == heap.size()) heap.add(HeapEntry());
+ int index = count++;
+ heap[index].value = value;
+ heap[index].priority = priority;
+ heap[index].sequence = enqueueCount++;
+ if (index == 0 || takesPriority(backIndex, index)) backIndex = index;
+ while (index > 0) {
+ int parent = (index - 1) / 2;
+ if (takesPriority(parent, index)) break;
+ swapHeapEntries(parent, index);
+ index = parent;
+ }
+}
+
+template <typename ValueType>
+void PriorityQueue<ValueType>::changePriority(ValueType value, double newPriority) {
+ // parts of this implementation are adapted from TrailblazerPQueue.h,
+ // which was written by Keith Schwarz
+
+ if (!(newPriority == newPriority)) {
+ error("PriorityQueue::changePriority(" + genericValueToString(value) + ", "
+ + realToString(newPriority) + "): Attempted to use NaN as a priority.");
+ }
+
+ // find the element in the pqueue; must use a simple iteration over elements
+ for (int i = 0; i < count; i++) {
+ if (heap[i].value == value) {
+ if (heap[i].priority < newPriority) {
+ error("PriorityQueue::changePriority(" + genericValueToString(value) + ", "
+ + realToString(newPriority)
+ + "): new priority cannot be less urgent than current priority of "
+ + realToString(heap[i].priority) + ".");
+ }
+ heap[i].priority = newPriority;
+
+ // after changing the priority, must percolate up to proper level
+ // to maintain heap ordering
+ while (i > 0) {
+ int parent = (i - 1) / 2;
+ if (takesPriority(parent, i)) break;
+ swapHeapEntries(parent, i);
+ i = parent;
+ }
+
+ return;
+ }
+ }
+
+ // if we get here, the element was not ever found
+ error("PriorityQueue::changePriority(" + genericValueToString(value) + ", "
+ + realToString(newPriority) + "): Element value not found.");
+}
+
+/*
+ * Implementation notes: dequeue, peek, peekPriority
+ * -------------------------------------------------
+ * These methods must check for an empty queue and report an error
+ * if there is no first element.
+ */
+
+template <typename ValueType>
+ValueType PriorityQueue<ValueType>::dequeue() {
+ if (count == 0) error("dequeue: Attempting to dequeue an empty queue");
+ count--;
+ bool wasBack = (backIndex == count);
+ ValueType value = heap[0].value;
+ swapHeapEntries(0, count);
+ int index = 0;
+ while (true) {
+ int left = 2 * index + 1;
+ int right = 2 * index + 2;
+ if (left >= count) break;
+ int child = left;
+ if (right < count && takesPriority(right, left)) child = right;
+ if (takesPriority(index, child)) break;
+ swapHeapEntries(index, child);
+ index = child;
+ }
+ if (wasBack) backIndex = index;
+ return value;
+}
+
+template <typename ValueType>
+ValueType PriorityQueue<ValueType>::peek() const {
+ if (count == 0) error("peek: Attempting to peek at an empty queue");
+ return heap.get(0).value;
+}
+
+template <typename ValueType>
+double PriorityQueue<ValueType>::peekPriority() const {
+ if (count == 0) error("peekPriority: Attempting to peek at an empty queue");
+ return heap.get(0).priority;
+}
+
+template <typename ValueType>
+ValueType & PriorityQueue<ValueType>::front() {
+ if (count == 0) error("front: Attempting to read front of an empty queue");
+ return heap.get(0).value;
+}
+
+template <typename ValueType>
+ValueType & PriorityQueue<ValueType>::back() {
+ if (count == 0) error("back: Attempting to read back of an empty queue");
+ return heap.get(backIndex).value;
+}
+
+template <typename ValueType>
+bool PriorityQueue<ValueType>::takesPriority(int i1, int i2) {
+ if (heap[i1].priority < heap[i2].priority) return true;
+ if (heap[i1].priority > heap[i2].priority) return false;
+ return (heap[i1].sequence < heap[i2].sequence);
+}
+
+template <typename ValueType>
+void PriorityQueue<ValueType>::swapHeapEntries(int i1, int i2) {
+ HeapEntry entry = heap[i1];
+ heap[i1] = heap[i2];
+ heap[i2] = entry;
+}
+
+template <typename ValueType>
+std::string PriorityQueue<ValueType>::toString() {
+ ostringstream os;
+ os << *this;
+ return os.str();
+}
+
+template <typename ValueType>
+std::ostream & operator<<(std::ostream & os,
+ const PriorityQueue<ValueType> & pq) {
+ os << "{";
+ PriorityQueue<ValueType> copy = pq;
+ int len = pq.size();
+ for (int i = 0; i < len; i++) {
+ if (i > 0) os << ", ";
+ os << copy.peekPriority() << ":";
+ writeGenericValue(os, copy.dequeue(), true);
+ }
+ return os << "}";
+}
+
+template <typename ValueType>
+std::istream & operator>>(std::istream & is, PriorityQueue<ValueType> & pq) {
+ char ch;
+ is >> ch;
+ if (ch != '{') error("operator >>: Missing {");
+ pq.clear();
+ is >> ch;
+ if (ch != '}') {
+ is.unget();
+ while (true) {
+ double priority;
+ is >> priority >> ch;
+ if (ch != ':') error("operator >>: Missing colon after priority");
+ ValueType value;
+ readGenericValue(is, value);
+ pq.enqueue(value, priority);
+ is >> ch;
+ if (ch == '}') break;
+ if (ch != ',') {
+ error(std::string("operator >>: Unexpected character ") + ch);
+ }
+ }
+ }
+ return is;
+}
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/private/main.h b/labb8/lib/StanfordCPPLib/private/main.h
new file mode 100755
index 0000000..698a97c
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/private/main.h
@@ -0,0 +1,58 @@
+/*
+ * File: main.h
+ * ------------
+ * This file renames the <code>main</code> method in the client's
+ * program to <code>Main</code>, thereby allowing a custom
+ * <code>main</code> method in the libraries to take control
+ * before passing control back to the client program. The main macro
+ * also defines a function getMainFlags that returns an int whose bits
+ * indicate which of the various interfaces have been loaded by this
+ * definition of main.
+ *
+ * Note: This file can be loaded more than once and must therefore
+ * check to see what has already been defined.
+ */
+
+#ifdef main
+# undef main
+# undef CONSOLE_FLAG
+# undef GRAPHICS_FLAG
+#else
+# define MAIN_USES_CONSOLE (1<<0)
+# define MAIN_USES_GRAPHICS (1<<1)
+#endif
+
+#ifdef _console_h
+# define CONSOLE_FLAG MAIN_USES_CONSOLE
+#else
+# define CONSOLE_FLAG 0
+#endif
+
+#ifdef _gwindow_h
+# define GRAPHICS_FLAG MAIN_USES_GRAPHICS
+#else
+# define GRAPHICS_FLAG 0
+#endif
+
+#if CONSOLE_FLAG | GRAPHICS_FLAG
+
+#define main main(int argc, char **argv) { \
+ extern int _mainFlags; \
+ _mainFlags = GRAPHICS_FLAG + CONSOLE_FLAG; \
+ return startupMain(argc, argv); \
+ } \
+ int Main
+
+extern int startupMain(int argc, char **argv);
+
+#else
+
+#define main main(int argc, char **argv) { \
+ extern int _mainFlags; \
+ _mainFlags = GRAPHICS_FLAG + CONSOLE_FLAG; \
+ return mainWrapper(argc, argv); } \
+ int Main
+
+extern int mainWrapper(int argc, char **argv);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/private/randompatch.h b/labb8/lib/StanfordCPPLib/private/randompatch.h
new file mode 100755
index 0000000..c7a4b86
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/private/randompatch.h
@@ -0,0 +1,63 @@
+/*
+ * File: private/randompatch.h
+ * ---------------------------
+ * This file patches the implementation of the random number library
+ * to avoid some serious bugs in standard implementations of rand,
+ * particularly on Mac OS X. It also includes a hack to set the
+ * seed from the RANDOM_SEED environment variable, which makes it
+ * possible to produce repeatable figures.
+ */
+
+/*
+ * Implementation notes: rand, srand
+ * ---------------------------------
+ * To ensure that this package works the same way on all platforms,
+ * this file completely reimplements the rand and srand methods. The
+ * algorithm is a conventional linear congruential generator with the
+ * parameters used in GNU's gclib. RAND_MAX for this implementation
+ * is 2147483647 (2^31 - 1).
+ */
+
+#define MULTIPLIER 1103515245
+#define OFFSET 12345
+
+static int _seed = 1;
+
+#undef rand
+#define rand() ((_seed = MULTIPLIER * _seed + OFFSET) & 0x7FFFFFFF)
+
+#undef srand
+#define srand(seed) (_seed = int(seed), _seed = (_seed <= 0) ? 1 : _seed)
+
+#undef RAND_MAX
+#define RAND_MAX 2147483647
+
+/*
+ * Implementation notes: Windows patch
+ * -----------------------------------
+ * On some versions of Windows, the time function is too coarse to use
+ * as a random seed. On those versions, this definition substitutes the
+ * GetTickCount function.
+ */
+
+#if defined (_MSC_VER) && (_MSC_VER >= 1200)
+# include <windows.h>
+# define time(dummy) (GetTickCount())
+#endif
+
+#ifdef __APPLE__
+
+# include <cstdlib>
+
+ static time_t patchedTime(time_t *) {
+ char *str = getenv("RANDOM_SEED");
+ if (str == NULL) {
+ return time(NULL);
+ } else {
+ return atoi(str);
+ }
+ }
+
+# define time(dummy) patchedTime(dummy)
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/private/tokenpatch.h b/labb8/lib/StanfordCPPLib/private/tokenpatch.h
new file mode 100755
index 0000000..d4930e5
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/private/tokenpatch.h
@@ -0,0 +1,11 @@
+/*
+ * File: tokenpatch.h
+ * ------------------
+ * This file renames TokenType and WORD to avoid conflict with the
+ * <windows.h> header.
+ */
+
+#ifdef _MSC_VER
+# define TokenType TokenTypeT
+# define WORD WORD_TC
+#endif
diff --git a/labb8/lib/StanfordCPPLib/private/tplatform.h b/labb8/lib/StanfordCPPLib/private/tplatform.h
new file mode 100755
index 0000000..6cf4bae
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/private/tplatform.h
@@ -0,0 +1,25 @@
+/*
+ * File: tplatform.h
+ * -----------------
+ * This interface defines the platform-specific methods on threads
+ * and locks.
+ */
+
+/* Methods for threads */
+
+int forkForPlatform(void (*fn)(void *), void *arg);
+void incThreadRefCountForPlatform(int id);
+void decThreadRefCountForPlatform(int id);
+void joinForPlatform(int id);
+int getCurrentThreadForPlatform();
+void yieldForPlatform();
+
+/* Methods for locks */
+
+int initLockForPlatform();
+void incLockRefCountForPlatform(int id);
+void decLockRefCountForPlatform(int id);
+void lockForPlatform(int id);
+void unlockForPlatform(int id);
+void waitForPlatform(int id);
+void signalForPlatform(int id);
diff --git a/labb8/lib/StanfordCPPLib/queue.h b/labb8/lib/StanfordCPPLib/queue.h
new file mode 100755
index 0000000..0d94a2c
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/queue.h
@@ -0,0 +1,372 @@
+/*
+ * File: queue.h
+ * -------------
+ * This file exports the <code>Queue</code> class, a collection
+ * in which values are ordinarily processed in a first-in/first-out
+ * (FIFO) order.
+ */
+
+#ifndef _queue_h
+#define _queue_h
+
+#include "vector.h"
+
+/*
+ * Class: Queue<ValueType>
+ * -----------------------
+ * This class models a linear structure called a <b><i>queue</i></b>
+ * in which values are added at one end and removed from the other.
+ * This discipline gives rise to a first-in/first-out behavior (FIFO)
+ * that is the defining feature of queues.
+ */
+
+template <typename ValueType>
+class Queue {
+
+public:
+
+/*
+ * Constructor: Queue
+ * Usage: Queue<ValueType> queue;
+ * ------------------------------
+ * Initializes a new empty queue.
+ */
+
+ Queue();
+
+/*
+ * Destructor: ~Queue
+ * ------------------
+ * Frees any heap storage associated with this queue.
+ */
+
+ virtual ~Queue();
+
+/*
+ * Method: size
+ * Usage: int n = queue.size();
+ * ----------------------------
+ * Returns the number of values in the queue.
+ */
+
+ int size() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (queue.isEmpty()) ...
+ * -------------------------------
+ * Returns <code>true</code> if the queue contains no elements.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: clear
+ * Usage: queue.clear();
+ * ---------------------
+ * Removes all elements from the queue.
+ */
+
+ void clear();
+
+/*
+ * Method: enqueue
+ * Usage: queue.enqueue(value);
+ * ----------------------------
+ * Adds <code>value</code> to the end of the queue.
+ */
+
+ void enqueue(ValueType value);
+
+/*
+ * Method: dequeue
+ * Usage: ValueType first = queue.dequeue();
+ * -----------------------------------------
+ * Removes and returns the first item in the queue.
+ */
+
+ ValueType dequeue();
+
+/*
+ * Method: peek
+ * Usage: ValueType first = queue.peek();
+ * --------------------------------------
+ * Returns the first value in the queue, without removing it. For
+ * compatibility with the STL classes, this method is also exported
+ * under the name <code>front</code>, in which case it returns the
+ * value by reference.
+ */
+
+ ValueType peek() const;
+
+/*
+ * Method: front
+ * Usage: ValueType first = queue.front();
+ * ---------------------------------------
+ * Returns the first value in the queue by reference.
+ */
+
+ ValueType & front();
+
+/*
+ * Method: back
+ * Usage: ValueType last = queue.back();
+ * -------------------------------------
+ * Returns the last value in the queue by reference.
+ */
+
+ ValueType & back();
+
+/*
+ * Method: toString
+ * Usage: string str = queue.toString();
+ * -------------------------------------
+ * Converts the queue to a printable string representation.
+ */
+
+ std::string toString();
+
+/*
+ * Operator: ==
+ * Usage: queue1 == queue2
+ * -------------------
+ * Returns <code>true</code> if <code>queue1</code> and <code>queue2</code>
+ * contain the same elements.
+ */
+
+ bool operator==(const Queue & queue2) const;
+
+/*
+ * Operator: !=
+ * Usage: queue1 != queue2
+ * -------------------
+ * Returns <code>true</code> if <code>queue1</code> and <code>queue2</code>
+ * do not contain the same elements.
+ */
+
+ bool operator!=(const Queue & queue2) const;
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+/*
+ * Implementation notes: Queue data structure
+ * ------------------------------------------
+ * The Queue class is implemented using a ring buffer.
+ */
+
+private:
+
+/* Instance variables */
+
+ Vector<ValueType> ringBuffer;
+ int count;
+ int capacity;
+ int head;
+ int tail;
+
+/* Private functions */
+
+ void expandRingBufferCapacity();
+
+};
+
+extern void error(std::string msg);
+
+/*
+ * Implementation notes: Queue data structure
+ * ------------------------------------------
+ * The array-based queue stores the elements in successive index
+ * positions in a vector, just as a stack does. What makes the
+ * queue structure more complex is the need to avoid shifting
+ * elements as the queue expands and contracts. In the array
+ * model, this goal is achieved by keeping track of both the
+ * head and tail indices. The tail index increases by one each
+ * time an element is enqueued, and the head index increases by
+ * one each time an element is dequeued. Each index therefore
+ * marches toward the end of the allocated vector and will
+ * eventually reach the end. Rather than allocate new memory,
+ * this implementation lets each index wrap around back to the
+ * beginning as if the ends of the array of elements were joined
+ * to form a circle. This representation is called a ring buffer.
+ */
+
+const int INITIAL_CAPACITY = 10;
+
+/*
+ * Implementation notes: Queue constructor
+ * ---------------------------------------
+ * The constructor must allocate the array storage for the queue
+ * elements and initialize the fields of the object.
+ */
+
+template <typename ValueType>
+Queue<ValueType>::Queue() {
+ clear();
+}
+
+/*
+ * Implementation notes: ~Queue destructor
+ * ---------------------------------------
+ * All of the dynamic memory is allocated in the Vector class,
+ * so no work is required at this level.
+ */
+
+template <typename ValueType>
+Queue<ValueType>::~Queue() {
+ /* Empty */
+}
+
+template <typename ValueType>
+int Queue<ValueType>::size() const {
+ return count;
+}
+
+template <typename ValueType>
+bool Queue<ValueType>::isEmpty() const {
+ return count == 0;
+}
+
+template <typename ValueType>
+void Queue<ValueType>::clear() {
+ capacity = INITIAL_CAPACITY;
+ ringBuffer = Vector<ValueType>(capacity);
+ head = 0;
+ tail = 0;
+ count = 0;
+}
+
+template <typename ValueType>
+void Queue<ValueType>::enqueue(ValueType value) {
+ if (count >= capacity - 1) expandRingBufferCapacity();
+ ringBuffer[tail] = value;
+ tail = (tail + 1) % capacity;
+ count++;
+}
+
+/*
+ * Implementation notes: dequeue, peek
+ * -----------------------------------
+ * These methods must check for an empty queue and report an error
+ * if there is no first element.
+ */
+
+template <typename ValueType>
+ValueType Queue<ValueType>::dequeue() {
+ if (count == 0) error("dequeue: Attempting to dequeue an empty queue");
+ ValueType result = ringBuffer[head];
+ head = (head + 1) % capacity;
+ count--;
+ return result;
+}
+
+template <typename ValueType>
+ValueType Queue<ValueType>::peek() const {
+ if (count == 0) error("peek: Attempting to peek at an empty queue");
+ return ringBuffer.get(head);
+}
+
+template <typename ValueType>
+ValueType & Queue<ValueType>::front() {
+ if (count == 0) error("front: Attempting to read front of an empty queue");
+ return ringBuffer[head];
+}
+
+template <typename ValueType>
+ValueType & Queue<ValueType>::back() {
+ if (count == 0) error("back: Attempting to read back of an empty queue");
+ return ringBuffer[(tail + capacity - 1) % capacity];
+}
+
+/*
+ * Implementation notes: expandRingBufferCapacity
+ * ----------------------------------------------
+ * This private method doubles the capacity of the ringBuffer vector.
+ * Note that this implementation also shifts all the elements back to
+ * the beginning of the vector.
+ */
+
+template <typename ValueType>
+void Queue<ValueType>::expandRingBufferCapacity() {
+ Vector<ValueType> copy = ringBuffer;
+ ringBuffer = Vector<ValueType>(2 * capacity);
+ for (int i = 0; i < count; i++) {
+ ringBuffer[i] = copy[(head + i) % capacity];
+ }
+ head = 0;
+ tail = count;
+ capacity *= 2;
+}
+
+template <typename ValueType>
+std::string Queue<ValueType>::toString() {
+ ostringstream os;
+ os << *this;
+ return os.str();
+}
+
+template <typename ValueType>
+bool Queue<ValueType>::operator==(const Queue & queue2) const {
+ if (size() != queue2.size()) return false;
+ Queue<ValueType> copy1 = *this;
+ Queue<ValueType> copy2 = queue2;
+ for (int i = 0; i < size(); i++) {
+ if (copy1.dequeue() != copy2.dequeue()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename ValueType>
+bool Queue<ValueType>::operator!=(const Queue & queue2) const {
+ return !(*this == queue2);
+}
+
+template <typename ValueType>
+std::ostream & operator<<(std::ostream & os, const Queue<ValueType> & queue) {
+ os << "{";
+ Queue<ValueType> copy = queue;
+ int len = queue.size();
+ for (int i = 0; i < len; i++) {
+ if (i > 0) os << ", ";
+ writeGenericValue(os, copy.dequeue(), true);
+ }
+ return os << "}";
+}
+
+template <typename ValueType>
+std::istream & operator>>(std::istream & is, Queue<ValueType> & queue) {
+ char ch;
+ is >> ch;
+ if (ch != '{') error("operator >>: Missing {");
+ queue.clear();
+ is >> ch;
+ if (ch != '}') {
+ is.unget();
+ while (true) {
+ ValueType value;
+ readGenericValue(is, value);
+ queue.enqueue(value);
+ is >> ch;
+ if (ch == '}') break;
+ if (ch != ',') {
+ error(std::string("operator >>: Unexpected character ") + ch);
+ }
+ }
+ }
+ return is;
+}
+
+// hashing functions for queues; defined in hashmap.cpp
+int hashCode(const Queue<std::string>& q);
+int hashCode(const Queue<int>& q);
+int hashCode(const Queue<char>& q);
+int hashCode(const Queue<long>& q);
+int hashCode(const Queue<double>& q);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/random.cpp b/labb8/lib/StanfordCPPLib/random.cpp
new file mode 100755
index 0000000..b7ea860
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/random.cpp
@@ -0,0 +1,99 @@
+/*
+ * File: random.cpp
+ * ----------------
+ * This file implements the random.h interface.
+ */
+
+#include <cstdlib>
+#include <cmath>
+#include <ctime>
+#include "random.h"
+#include "private/randompatch.h"
+using namespace std;
+
+/* Private function prototype */
+
+static void initRandomSeed();
+
+/*
+ * Implementation notes: randomInteger
+ * -----------------------------------
+ * The code for randomInteger produces the number in four steps:
+ *
+ * 1. Generate a random real number d in the range [0 .. 1).
+ * 2. Scale the number to the range [0 .. N) where N is the number of values.
+ * 3. Translate the number so that the range starts at the appropriate value.
+ * 4. Convert the result to the next lower integer.
+ *
+ * The implementation is complicated by the fact that both the expression
+ *
+ * RAND_MAX + 1
+ *
+ * and the expression for the number of values
+ *
+ * high - low + 1
+ *
+ * can overflow the integer range. These calculations must therefore be
+ * performed using doubles instead of ints.
+ */
+
+int randomInteger(int low, int high) {
+ initRandomSeed();
+ double d = rand() / (double(RAND_MAX) + 1);
+ double s = d * (double(high) - low + 1);
+ return int(floor(low + s));
+}
+
+/*
+ * Implementation notes: randomReal
+ * --------------------------------
+ * The code for randomReal is similar to that for randomInteger,
+ * without the final conversion step.
+ */
+
+double randomReal(double low, double high) {
+ initRandomSeed();
+ double d = rand() / (double(RAND_MAX) + 1);
+ double s = d * (high - low);
+ return low + s;
+}
+
+/*
+ * Implementation notes: randomChance
+ * ----------------------------------
+ * The code for randomChance calls randomReal(0, 1) and then checks
+ * whether the result is less than the requested probability.
+ */
+
+bool randomChance(double p) {
+ initRandomSeed();
+ return randomReal(0, 1) < p;
+}
+
+/*
+ * Implementation notes: setRandomSeed
+ * -----------------------------------
+ * The setRandomSeed function simply forwards its argument to srand.
+ * The call to initRandomSeed is required to set the initialized flag.
+ */
+
+void setRandomSeed(int seed) {
+ initRandomSeed();
+ srand(seed);
+}
+
+/*
+ * Implementation notes: initRandomSeed
+ * ------------------------------------
+ * The initRandomSeed function declares a static variable that keeps track
+ * of whether the seed has been initialized. The first time initRandomSeed
+ * is called, initialized is false, so the seed is set to the current time.
+ */
+
+static void initRandomSeed() {
+ static bool initialized = false;
+ if (!initialized) {
+ srand(int(time(NULL)));
+ initialized = true;
+ }
+}
diff --git a/labb8/lib/StanfordCPPLib/random.h b/labb8/lib/StanfordCPPLib/random.h
new file mode 100755
index 0000000..3286f8f
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/random.h
@@ -0,0 +1,58 @@
+/*
+ * File: random.h
+ * --------------
+ * This file exports functions for generating pseudorandom numbers.
+ */
+
+#ifndef _random_h
+#define _random_h
+
+/*
+ * Function: randomInteger
+ * Usage: int n = randomInteger(low, high);
+ * ----------------------------------------
+ * Returns a random integer in the range <code>low</code> to
+ * <code>high</code>, inclusive.
+ */
+
+int randomInteger(int low, int high);
+
+/*
+ * Function: randomReal
+ * Usage: double d = randomReal(low, high);
+ * ----------------------------------------
+ * Returns a random real number in the half-open interval
+ * [<code>low</code>&nbsp;..&nbsp;<code>high</code>). A half-open
+ * interval includes the first endpoint but not the second, which
+ * means that the result is always greater than or equal to
+ * <code>low</code> but strictly less than <code>high</code>.
+ */
+
+double randomReal(double low, double high);
+
+/*
+ * Function: randomChance
+ * Usage: if (randomChance(p)) ...
+ * -------------------------------
+ * Returns <code>true</code> with the probability indicated by <code>p</code>.
+ * The argument <code>p</code> must be a floating-point number between
+ * 0 (never) and 1 (always). For example, calling
+ * <code>randomChance(.30)</code> returns <code>true</code> 30 percent
+ * of the time.
+ */
+
+bool randomChance(double p);
+
+/*
+ * Function: setRandomSeed
+ * Usage: setRandomSeed(seed);
+ * ---------------------------
+ * Sets the internal random number seed to the specified value. You
+ * can use this function to set a specific starting point for the
+ * pseudorandom sequence or to ensure that program behavior is
+ * repeatable during the debugging phase.
+ */
+
+void setRandomSeed(int seed);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/set.h b/labb8/lib/StanfordCPPLib/set.h
new file mode 100755
index 0000000..4395fa5
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/set.h
@@ -0,0 +1,621 @@
+/*
+ * File: set.h
+ * -----------
+ * This file exports the <code>Set</code> class, which implements a
+ * collection for storing a set of distinct elements.
+ */
+
+#ifndef _set_h
+#define _set_h
+
+#include <iostream>
+#include "foreach.h"
+#include "map.h"
+#include "vector.h"
+
+/*
+ * Class: Set<ValueType>
+ * ---------------------
+ * This class stores a collection of distinct elements.
+ */
+
+template <typename ValueType>
+class Set {
+
+public:
+
+/*
+ * Constructor: Set
+ * Usage: Set<ValueType> set;
+ * --------------------------
+ * Creates an empty set of the specified element type.
+ */
+
+ Set();
+
+/*
+ * Destructor: ~Set
+ * ----------------
+ * Frees any heap storage associated with this set.
+ */
+
+ virtual ~Set();
+
+/*
+ * Method: size
+ * Usage: count = set.size();
+ * --------------------------
+ * Returns the number of elements in this set.
+ */
+
+ int size() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (set.isEmpty()) ...
+ * -----------------------------
+ * Returns <code>true</code> if this set contains no elements.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: add
+ * Usage: set.add(value);
+ * ----------------------
+ * Adds an element to this set, if it was not already there. For
+ * compatibility with the STL <code>set</code> class, this method
+ * is also exported as <code>insert</code>.
+ */
+
+ void add(const ValueType & value);
+ void insert(const ValueType & value);
+
+/*
+ * Method: remove
+ * Usage: set.remove(value);
+ * -------------------------
+ * Removes an element from this set. If the value was not
+ * contained in the set, no error is generated and the set
+ * remains unchanged.
+ */
+
+ void remove(const ValueType & value);
+
+/*
+ * Method: contains
+ * Usage: if (set.contains(value)) ...
+ * -----------------------------------
+ * Returns <code>true</code> if the specified value is in this set.
+ */
+
+ bool contains(const ValueType & value) const;
+
+/*
+ * Method: isSubsetOf
+ * Usage: if (set.isSubsetOf(set2)) ...
+ * ------------------------------------
+ * Implements the subset relation on sets. It returns
+ * <code>true</code> if every element of this set is
+ * contained in <code>set2</code>.
+ */
+
+ bool isSubsetOf(const Set & set2) const;
+
+/*
+ * Method: clear
+ * Usage: set.clear();
+ * -------------------
+ * Removes all elements from this set.
+ */
+
+ void clear();
+
+/*
+ * Operator: ==
+ * Usage: set1 == set2
+ * -------------------
+ * Returns <code>true</code> if <code>set1</code> and <code>set2</code>
+ * contain the same elements.
+ */
+
+ bool operator==(const Set & set2) const;
+
+/*
+ * Operator: !=
+ * Usage: set1 != set2
+ * -------------------
+ * Returns <code>true</code> if <code>set1</code> and <code>set2</code>
+ * are different.
+ */
+
+ bool operator!=(const Set & set2) const;
+
+/*
+ * Operator: +
+ * Usage: set1 + set2
+ * set1 + element
+ * ---------------------
+ * Returns the union of sets <code>set1</code> and <code>set2</code>, which
+ * is the set of elements that appear in at least one of the two sets. The
+ * right hand set can be replaced by an element of the value type, in which
+ * case the operator returns a new set formed by adding that element.
+ */
+
+ Set operator+(const Set & set2) const;
+ Set operator+(const ValueType & element) const;
+
+/*
+ * Operator: *
+ * Usage: set1 * set2
+ * ------------------
+ * Returns the intersection of sets <code>set1</code> and <code>set2</code>,
+ * which is the set of all elements that appear in both.
+ */
+
+ Set operator*(const Set & set2) const;
+
+/*
+ * Operator: -
+ * Usage: set1 - set2
+ * set1 - element
+ * ---------------------
+ * Returns the difference of sets <code>set1</code> and <code>set2</code>,
+ * which is all of the elements that appear in <code>set1</code> but
+ * not <code>set2</code>. The right hand set can be replaced by an
+ * element of the value type, in which case the operator returns a new
+ * set formed by removing that element.
+ */
+
+ Set operator-(const Set & set2) const;
+ Set operator-(const ValueType & element) const;
+
+/*
+ * Operator: +=
+ * Usage: set1 += set2;
+ * set1 += value;
+ * ---------------------
+ * Adds all of the elements from <code>set2</code> (or the single
+ * specified value) to <code>set1</code>. As a convenience, the
+ * <code>Set</code> package also overloads the comma operator so
+ * that it is possible to initialize a set like this:
+ *
+ *<pre>
+ * Set<int> digits;
+ * digits += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
+ *</pre>
+ */
+
+ Set & operator+=(const Set & set2);
+ Set & operator+=(const ValueType & value);
+
+/*
+ * Operator: *=
+ * Usage: set1 *= set2;
+ * --------------------
+ * Removes any elements from <code>set1</code> that are not present in
+ * <code>set2</code>.
+ */
+
+ Set & operator*=(const Set & set2);
+
+/*
+ * Operator: -=
+ * Usage: set1 -= set2;
+ * set1 -= value;
+ * ---------------------
+ * Removes the elements from <code>set2</code> (or the single
+ * specified value) from <code>set1</code>. As a convenience, the
+ * <code>Set</code> package also overloads the comma operator so
+ * that it is possible to remove multiple elements from a set
+ * like this:
+ *
+ *<pre>
+ * digits -= 0, 2, 4, 6, 8;
+ *</pre>
+ *
+ * which removes the values 0, 2, 4, 6, and 8 from the set
+ * <code>digits</code>.
+ */
+
+ Set & operator-=(const Set & set2);
+ Set & operator-=(const ValueType & value);
+
+/*
+ * Method: first
+ * Usage: ValueType value = set.first();
+ * -------------------------------------
+ * Returns the first value in the set in the order established by the
+ * <code>foreach</code> macro. If the set is empty, <code>first</code>
+ * generates an error.
+ */
+
+ ValueType first() const;
+
+/*
+ * Method: toString
+ * Usage: string str = set.toString();
+ * -----------------------------------
+ * Converts the set to a printable string representation.
+ */
+
+ std::string toString();
+
+/*
+ * Method: mapAll
+ * Usage: set.mapAll(fn);
+ * ----------------------
+ * Iterates through the elements of the set and calls <code>fn(value)</code>
+ * for each one. The values are processed in ascending order, as defined
+ * by the comparison function.
+ */
+
+ void mapAll(void (*fn)(ValueType)) const;
+ void mapAll(void (*fn)(const ValueType &)) const;
+
+ template <typename FunctorType>
+ void mapAll(FunctorType fn) const;
+
+/*
+ * Additional Set operations
+ * -------------------------
+ * In addition to the methods listed in this interface, the Set class
+ * supports the following operations:
+ *
+ * - Stream I/O using the << and >> operators
+ * - Deep copying for the copy constructor and assignment operator
+ * - Iteration using the range-based for statement and STL iterators
+ *
+ * The iteration forms process the Set in ascending order.
+ */
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+private:
+
+ Map<ValueType,bool> map; /* Map used to store the element */
+ bool removeFlag; /* Flag to differentiate += and -= */
+
+public:
+
+/*
+ * Hidden features
+ * ---------------
+ * The remainder of this file consists of the code required to
+ * support the comma operator, deep copying, and iteration.
+ * Including these methods in the public interface would make
+ * that interface more difficult to understand for the average client.
+ */
+
+/* Extended constructors */
+
+ template <typename CompareType>
+ explicit Set(CompareType cmp) : map(Map<ValueType,bool>(cmp)) {
+ /* Empty */
+ }
+
+ Set & operator,(const ValueType & value) {
+ if (this->removeFlag) {
+ this->remove(value);
+ } else {
+ this->add(value);
+ }
+ return *this;
+ }
+
+/*
+ * Iterator support
+ * ----------------
+ * The classes in the StanfordCPPLib collection implement input
+ * iterators so that they work symmetrically with respect to the
+ * corresponding STL classes.
+ */
+
+ class iterator : public std::iterator<std::input_iterator_tag,ValueType> {
+
+ private:
+
+ typename Map<ValueType,bool>::iterator mapit; /* Iterator for the map */
+
+ public:
+
+ iterator() {
+ /* Empty */
+ }
+
+ iterator(typename Map<ValueType,bool>::iterator it) : mapit(it) {
+ /* Empty */
+ }
+
+ iterator(const iterator & it) {
+ mapit = it.mapit;
+ }
+
+ iterator & operator++() {
+ ++mapit;
+ return *this;
+ }
+
+ iterator operator++(int) {
+ iterator copy(*this);
+ operator++();
+ return copy;
+ }
+
+ bool operator==(const iterator & rhs) {
+ return mapit == rhs.mapit;
+ }
+
+ bool operator!=(const iterator & rhs) {
+ return !(*this == rhs);
+ }
+
+ ValueType operator*() {
+ return *mapit;
+ }
+
+ ValueType *operator->() {
+ return mapit;
+ }
+ };
+
+ iterator begin() const {
+ return iterator(map.begin());
+ }
+
+ iterator end() const {
+ return iterator(map.end());
+ }
+
+};
+
+extern void error(std::string msg);
+
+template <typename ValueType>
+Set<ValueType>::Set() {
+ /* Empty */
+}
+
+template <typename ValueType>
+Set<ValueType>::~Set() {
+ /* Empty */
+}
+
+template <typename ValueType>
+int Set<ValueType>::size() const {
+ return map.size();
+}
+
+template <typename ValueType>
+bool Set<ValueType>::isEmpty() const {
+ return map.isEmpty();
+}
+
+template <typename ValueType>
+void Set<ValueType>::add(const ValueType & value) {
+ map.put(value, true);
+}
+
+template <typename ValueType>
+void Set<ValueType>::insert(const ValueType & value) {
+ map.put(value, true);
+}
+
+template <typename ValueType>
+void Set<ValueType>::remove(const ValueType & value) {
+ map.remove(value);
+}
+
+template <typename ValueType>
+bool Set<ValueType>::contains(const ValueType & value) const {
+ return map.containsKey(value);
+}
+
+template <typename ValueType>
+void Set<ValueType>::clear() {
+ map.clear();
+}
+
+template <typename ValueType>
+bool Set<ValueType>::isSubsetOf(const Set & set2) const {
+ iterator it = begin();
+ iterator end = this->end();
+ while (it != end) {
+ if (!set2.map.containsKey(*it)) return false;
+ ++it;
+ }
+ return true;
+}
+
+/*
+ * Implementation notes: set operators
+ * -----------------------------------
+ * The implementations for the set operators use iteration to walk
+ * over the elements in one or both sets.
+ */
+
+template <typename ValueType>
+bool Set<ValueType>::operator==(const Set & set2) const {
+ if (size() != set2.map.size()) return false;
+ iterator it1 = begin();
+ iterator it2 = set2.map.begin();
+ iterator end = this->end();
+ while (it1 != end) {
+ if (map.compareKeys(*it1, *it2) != 0) return false;
+ ++it1;
+ ++it2;
+ }
+ return true;
+}
+
+template <typename ValueType>
+bool Set<ValueType>::operator!=(const Set & set2) const {
+ return !(*this == set2);
+}
+
+template <typename ValueType>
+Set<ValueType> Set<ValueType>::operator+(const Set & set2) const {
+ Set<ValueType> set = *this;
+ foreach (ValueType value in set2) {
+ set.add(value);
+ }
+ return set;
+}
+
+template <typename ValueType>
+Set<ValueType> Set<ValueType>::operator+(const ValueType & element) const {
+ Set<ValueType> set = *this;
+ set.add(element);
+ return set;
+}
+
+template <typename ValueType>
+Set<ValueType> Set<ValueType>::operator*(const Set & set2) const {
+ Set<ValueType> set = *this;
+ set.clear();
+ foreach (ValueType value in *this) {
+ if (set2.contains(value)) set.add(value);
+ }
+ return set;
+}
+
+template <typename ValueType>
+Set<ValueType> Set<ValueType>::operator-(const Set & set2) const {
+ Set<ValueType> set = *this;
+ foreach (ValueType value in set2) {
+ set.remove(value);
+ }
+ return set;
+}
+
+template <typename ValueType>
+Set<ValueType> Set<ValueType>::operator-(const ValueType & element) const {
+ Set<ValueType> set = *this;
+ set.remove(element);
+ return set;
+}
+
+template <typename ValueType>
+Set<ValueType> & Set<ValueType>::operator+=(const Set & set2) {
+ foreach (ValueType value in set2) {
+ this->add(value);
+ }
+ return *this;
+}
+
+template <typename ValueType>
+Set<ValueType> & Set<ValueType>::operator+=(const ValueType & value) {
+ this->add(value);
+ this->removeFlag = false;
+ return *this;
+}
+
+template <typename ValueType>
+Set<ValueType> & Set<ValueType>::operator*=(const Set & set2) {
+ Vector<ValueType> toRemove;
+ foreach (ValueType value in *this) {
+ if (!set2.map.containsKey(value)) toRemove.add(value);
+ }
+ foreach (ValueType value in toRemove) {
+ this->remove(value);
+ }
+ return *this;
+}
+
+template <typename ValueType>
+Set<ValueType> & Set<ValueType>::operator-=(const Set & set2) {
+ Vector<ValueType> toRemove;
+ foreach (ValueType value in *this) {
+ if (set2.map.containsKey(value)) toRemove.add(value);
+ }
+ foreach (ValueType value in toRemove) {
+ this->remove(value);
+ }
+ return *this;
+}
+
+template <typename ValueType>
+Set<ValueType> & Set<ValueType>::operator-=(const ValueType & value) {
+ this->remove(value);
+ this->removeFlag = true;
+ return *this;
+}
+
+template <typename ValueType>
+ValueType Set<ValueType>::first() const {
+ if (isEmpty()) error("first: set is empty");
+ return *begin();
+}
+
+template <typename ValueType>
+std::string Set<ValueType>::toString() {
+ ostringstream os;
+ os << *this;
+ return os.str();
+}
+
+template <typename ValueType>
+void Set<ValueType>::mapAll(void (*fn)(ValueType)) const {
+ map.mapAll(fn);
+}
+
+template <typename ValueType>
+void Set<ValueType>::mapAll(void (*fn)(const ValueType &)) const {
+ map.mapAll(fn);
+}
+
+template <typename ValueType>
+template <typename FunctorType>
+void Set<ValueType>::mapAll(FunctorType fn) const {
+ map.mapAll(fn);
+}
+
+template <typename ValueType>
+std::ostream & operator<<(std::ostream & os, const Set<ValueType> & set) {
+ os << "{";
+ bool started = false;
+ foreach (ValueType value in set) {
+ if (started) os << ", ";
+ writeGenericValue(os, value, true);
+ started = true;
+ }
+ os << "}";
+ return os;
+}
+
+template <typename ValueType>
+std::istream & operator>>(std::istream & is, Set<ValueType> & set) {
+ char ch;
+ is >> ch;
+ if (ch != '{') error("operator >>: Missing {");
+ set.clear();
+ is >> ch;
+ if (ch != '}') {
+ is.unget();
+ while (true) {
+ ValueType value;
+ readGenericValue(is, value);
+ set += value;
+ is >> ch;
+ if (ch == '}') break;
+ if (ch != ',') {
+ error(std::string("operator >>: Unexpected character ") + ch);
+ }
+ }
+ }
+ return is;
+}
+
+// hashing functions for sets; defined in hashmap.cpp
+int hashCode(const Set<std::string>& s);
+int hashCode(const Set<int>& s);
+int hashCode(const Set<char>& s);
+int hashCode(const Set<long>& s);
+int hashCode(const Set<double>& s);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/simpio.cpp b/labb8/lib/StanfordCPPLib/simpio.cpp
new file mode 100755
index 0000000..4f91551
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/simpio.cpp
@@ -0,0 +1,67 @@
+/*
+ * File: simpio.cpp
+ * ----------------
+ * This file implements the simpio.h interface.
+ */
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include "simpio.h"
+using namespace std;
+
+/*
+ * Implementation notes: getInteger, getReal
+ * -----------------------------------------
+ * Each of these functions reads a complete input line and then uses the
+ * <sstream> library to parse that line into a value of the desired type.
+ * If that fails, the implementation asks the user for a new value.
+ */
+
+int getInteger(string prompt) {
+ int value;
+ string line;
+ while (true) {
+ cout << prompt;
+ getline(cin, line);
+ istringstream stream(line);
+ stream >> value >> ws;
+ if (!stream.fail() && stream.eof()) break;
+ cout << "Illegal integer format. Try again." << endl;
+ if (prompt == "") prompt = "Enter an integer: ";
+ }
+ return value;
+}
+
+double getReal(string prompt) {
+ double value;
+ string line;
+ while (true) {
+ cout << prompt;
+ getline(cin, line);
+ istringstream stream(line);
+ stream >> value >> ws;
+ if (!stream.fail() && stream.eof()) break;
+ cout << "Illegal numeric format. Try again." << endl;
+ if (prompt == "") prompt = "Enter a number: ";
+ }
+ return value;
+}
+
+/*
+ * Implementation notes: getLine
+ * -----------------------------
+ * The getLine function simply combines the process of displaying a
+ * prompt and reading an input line into a single call. The primary
+ * reason for including this function in the library is to ensure
+ * that the process of reading integers, floating-point numbers, and
+ * strings remains as consistent as possible.
+ */
+
+string getLine(string prompt) {
+ string line;
+ cout << prompt;
+ getline(cin, line);
+ return line;
+}
diff --git a/labb8/lib/StanfordCPPLib/simpio.h b/labb8/lib/StanfordCPPLib/simpio.h
new file mode 100755
index 0000000..25c32c1
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/simpio.h
@@ -0,0 +1,53 @@
+/*
+ * File: simpio.h
+ * --------------
+ * This file exports a set of functions that simplify input/output
+ * operations in C++ and provide some error-checking on console input.
+ */
+
+#ifndef _simpio_h
+#define _simpio_h
+
+#include <string>
+
+/*
+ * Function: getInteger
+ * Usage: int n = getInteger(prompt);
+ * ----------------------------------
+ * Reads a complete line from <code>cin</code> and scans it as an
+ * integer. If the scan succeeds, the integer value is returned. If
+ * the argument is not a legal integer or if extraneous characters
+ * (other than whitespace) appear in the string, the user is given
+ * a chance to reenter the value. If supplied, the optional
+ * <code>prompt</code> string is printed before reading the value.
+ */
+
+int getInteger(std::string prompt = "");
+
+/*
+ * Function: getReal
+ * Usage: double x = getReal(prompt);
+ * ----------------------------------
+ * Reads a complete line from <code>cin</code> and scans it as a
+ * floating-point number. If the scan succeeds, the floating-point
+ * value is returned. If the input is not a legal number or if
+ * extraneous characters (other than whitespace) appear in the string,
+ * the user is given a chance to reenter the value. If supplied, the
+ * optional <code>prompt</code> string is printed before reading the value.
+ */
+
+double getReal(std::string prompt = "");
+
+/*
+ * Function: getLine
+ * Usage: string line = getLine(prompt);
+ * -------------------------------------
+ * Reads a line of text from <code>cin</code> and returns that line
+ * as a string. The newline character that terminates the input is
+ * not stored as part of the return value. If supplied, the optional
+ * <code>prompt</code> string is printed before reading the value.
+ */
+
+std::string getLine(std::string prompt = "");
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/sound.cpp b/labb8/lib/StanfordCPPLib/sound.cpp
new file mode 100755
index 0000000..f0c4705
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/sound.cpp
@@ -0,0 +1,31 @@
+/*
+ * File: sound.cpp
+ * ---------------
+ * Implementation of the Sound class.
+ */
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+#include "gevents.h"
+#include "gtypes.h"
+#include "sound.h"
+#include "vector.h"
+#include "platform.h"
+using namespace std;
+
+static Platform *pp = getPlatform();
+
+Sound::Sound(string filename) {
+ pp->createSound(this, filename);
+}
+
+Sound::~Sound() {
+ pp->deleteSound(this);
+}
+
+void Sound::play() {
+ pp->playSound(this);
+}
+
diff --git a/labb8/lib/StanfordCPPLib/sound.h b/labb8/lib/StanfordCPPLib/sound.h
new file mode 100755
index 0000000..89e2066
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/sound.h
@@ -0,0 +1,63 @@
+/*
+ * File: sound.h
+ * -------------
+ * This file defines a class that represents a sound.
+ */
+
+#ifndef _sound_h
+#define _sound_h
+
+/*
+ * Class: Sound
+ * ------------
+ * This class encapsulates a sound file. The sound file is specified in the
+ * constructor and must be a file in either the current directory or a
+ * subdirectory named <code>sounds</code>.
+ *
+ * <p>The following code, for example, plays the sound file
+ * <code>ringtone.wav</code>:
+ *
+ *<pre>
+ * Sound ringtone("ringtone.wav");
+ * ringtone.play();
+ *</pre>
+ */
+
+class Sound {
+
+public:
+
+/*
+ * Constructor: Sound
+ * Usage: Sound sound;
+ * Sound sound(filename);
+ * -----------------------------
+ * Creates a <code>Sound</code> object. The default constructor
+ * creates an empty sound that cannot be played. The second form
+ * initializes the sound by reading in the contents of the specified
+ * file.
+ */
+
+ Sound(std::string filename);
+
+/*
+ * Destructor: ~Sound
+ * ------------------
+ * Frees the memory associated with the sound.
+ */
+
+ virtual ~Sound();
+
+/*
+ * Method: play
+ * Usage: sound.play();
+ * --------------------
+ * Starts playing the sound. This call returns immediately without waiting
+ * for the sound to finish.
+ */
+
+ void play();
+
+};
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/stack.h b/labb8/lib/StanfordCPPLib/stack.h
new file mode 100755
index 0000000..21d5058
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/stack.h
@@ -0,0 +1,285 @@
+/*
+ * File: stack.h
+ * -------------
+ * This file exports the <code>Stack</code> class, which implements
+ * a collection that processes values in a last-in/first-out (LIFO) order.
+ */
+
+#ifndef _stack_h
+#define _stack_h
+
+#include "vector.h"
+
+/*
+ * Class: Stack<ValueType>
+ * -----------------------
+ * This class models a linear structure called a <b><i>stack</i></b>
+ * in which values are added and removed only from one end.
+ * This discipline gives rise to a last-in/first-out behavior (LIFO)
+ * that is the defining feature of stacks. The fundamental stack
+ * operations are <code>push</code> (add to top) and <code>pop</code>
+ * (remove from top).
+ */
+
+template <typename ValueType>
+class Stack {
+
+public:
+
+/*
+ * Constructor: Stack
+ * Usage: Stack<ValueType> stack;
+ * ------------------------------
+ * Initializes a new empty stack.
+ */
+
+ Stack();
+
+/*
+ * Destructor: ~Stack
+ * ------------------
+ * Frees any heap storage associated with this stack.
+ */
+
+ virtual ~Stack();
+
+/*
+ * Method: size
+ * Usage: int n = stack.size();
+ * ----------------------------
+ * Returns the number of values in this stack.
+ */
+
+ int size() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (stack.isEmpty()) ...
+ * -------------------------------
+ * Returns <code>true</code> if this stack contains no elements.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: clear
+ * Usage: stack.clear();
+ * ---------------------
+ * Removes all elements from this stack.
+ */
+
+ void clear();
+
+/*
+ * Method: push
+ * Usage: stack.push(value);
+ * -------------------------
+ * Pushes the specified value onto this stack.
+ */
+
+ void push(ValueType value);
+
+/*
+ * Method: pop
+ * Usage: ValueType top = stack.pop();
+ * -----------------------------------
+ * Removes the top element from this stack and returns it. This
+ * method signals an error if called on an empty stack.
+ */
+
+ ValueType pop();
+
+/*
+ * Method: peek
+ * Usage: ValueType top = stack.peek();
+ * ------------------------------------
+ * Returns the value of top element from this stack, without removing
+ * it. This method signals an error if called on an empty stack. For
+ * compatibility with the STL classes, this method is also exported
+ * under the name <code>top</code>, in which case it returns the value
+ * by reference.
+ */
+
+ ValueType peek() const;
+ ValueType & top();
+
+/*
+ * Method: toString
+ * Usage: string str = stack.toString();
+ * -------------------------------------
+ * Converts the stack to a printable string representation.
+ */
+
+ std::string toString();
+
+/*
+ * Operator: ==
+ * Usage: stack1 == stack2
+ * -------------------
+ * Returns <code>true</code> if <code>stack1</code> and <code>stack2</code>
+ * contain the same elements.
+ */
+
+ bool operator==(const Stack & stack2) const;
+
+/*
+ * Operator: !=
+ * Usage: stack1 != stack2
+ * -------------------
+ * Returns <code>true</code> if <code>stack1</code> and <code>stack2</code>
+ * do not contain the same elements.
+ */
+
+ bool operator!=(const Stack & stack2) const;
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+/*
+ * Implementation notes: Stack data structure
+ * ------------------------------------------
+ * The easiest way to implement a stack is to store the elements in a
+ * Vector. Doing so means that the problems of dynamic memory allocation
+ * and copy assignment are already solved by the implementation of the
+ * underlying Vector class.
+ */
+
+private:
+ Vector<ValueType> elements;
+
+};
+
+extern void error(std::string msg);
+
+/*
+ * Stack class implementation
+ * --------------------------
+ * The Stack is internally managed using a Vector. This layered design
+ * makes the implementation extremely simple, to the point that most
+ * methods can be implemented in as single line.
+ */
+
+template <typename ValueType>
+Stack<ValueType>::Stack() {
+ /* Empty */
+}
+
+template <typename ValueType>
+Stack<ValueType>::~Stack() {
+ /* Empty */
+}
+
+template <typename ValueType>
+int Stack<ValueType>::size() const {
+ return elements.size();
+}
+
+template <typename ValueType>
+bool Stack<ValueType>::isEmpty() const {
+ return size() == 0;
+}
+
+template <typename ValueType>
+void Stack<ValueType>::push(ValueType value) {
+ elements.add(value);
+}
+
+template <typename ValueType>
+ValueType Stack<ValueType>::pop() {
+ if (isEmpty()) error("pop: Attempting to pop an empty stack");
+ ValueType top = elements[elements.size() - 1];
+ elements.remove(elements.size() - 1);
+ return top;
+}
+
+template <typename ValueType>
+ValueType Stack<ValueType>::peek() const {
+ if (isEmpty()) error("peek: Attempting to peek at an empty stack");
+ return elements.get(elements.size() - 1);
+}
+
+template <typename ValueType>
+ValueType & Stack<ValueType>::top() {
+ if (isEmpty()) error("top: Attempting to read top of an empty stack");
+ return elements[elements.size() - 1];
+}
+
+template <typename ValueType>
+void Stack<ValueType>::clear() {
+ elements.clear();
+}
+
+template <typename ValueType>
+std::string Stack<ValueType>::toString() {
+ ostringstream os;
+ os << *this;
+ return os.str();
+}
+
+template <typename ValueType>
+bool Stack<ValueType>::operator==(const Stack & stack2) const {
+ if (size() != stack2.size()) return false;
+ for (int i = 0; i < size(); i++) {
+ if (this->elements[i] != stack2.elements[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename ValueType>
+bool Stack<ValueType>::operator!=(const Stack & stack2) const {
+ return !(*this == stack2);
+}
+
+template <typename ValueType>
+std::ostream & operator<<(std::ostream & os, const Stack<ValueType> & stack) {
+ os << "{";
+ Stack<ValueType> copy = stack;
+ Stack<ValueType> reversed;
+ while (!copy.isEmpty()) {
+ reversed.push(copy.pop());
+ }
+ int len = stack.size();
+ for (int i = 0; i < len; i++) {
+ if (i > 0) os << ", ";
+ writeGenericValue(os, reversed.pop(), true);
+ }
+ return os << "}";
+}
+
+template <typename ValueType>
+std::istream & operator>>(std::istream & is, Stack<ValueType> & stack) {
+ char ch;
+ is >> ch;
+ if (ch != '{') error("operator >>: Missing {");
+ stack.clear();
+ is >> ch;
+ if (ch != '}') {
+ is.unget();
+ while (true) {
+ ValueType value;
+ readGenericValue(is, value);
+ stack.push(value);
+ is >> ch;
+ if (ch == '}') break;
+ if (ch != ',') {
+ error(std::string("operator >>: Unexpected character ") + ch);
+ }
+ }
+ }
+ return is;
+}
+
+// hashing functions for stacks; defined in hashmap.cpp
+int hashCode(const Stack<std::string>& s);
+int hashCode(const Stack<int>& s);
+int hashCode(const Stack<char>& s);
+int hashCode(const Stack<long>& s);
+int hashCode(const Stack<double>& s);
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/startup.cpp b/labb8/lib/StanfordCPPLib/startup.cpp
new file mode 100755
index 0000000..d6d3ff8
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/startup.cpp
@@ -0,0 +1,34 @@
+/*
+ * File: startup.cpp
+ * -----------------
+ * This file implements the wrapper for main that allows for
+ * system initialization and error handling.
+ */
+
+#include <cstdlib>
+#include <iostream>
+#include "error.h"
+using namespace std;
+
+#if defined (_MSC_VER) && (_MSC_VER >= 1200)
+# include <windows.h>
+# define MSC_ERROR_FLAGS (MB_OK | MB_ICONSTOP | MB_TOPMOST)
+#endif
+
+/* Global flag word indicating option for main */
+
+int _mainFlags;
+
+int mainWrapper(int argc, char **argv) {
+ extern int Main(int argc, char **argv);
+ try {
+ return Main(argc, argv);
+ } catch (ErrorException & ex) {
+ string msg = "Error: " + ex.getMessage();
+ cerr << msg << endl;
+#ifdef _MSC_VER
+ MessageBoxA(NULL, msg.c_str(), "Error!", MSC_ERROR_FLAGS);
+#endif
+ return EXIT_FAILURE;
+ }
+}
diff --git a/labb8/lib/StanfordCPPLib/strlib.cpp b/labb8/lib/StanfordCPPLib/strlib.cpp
new file mode 100755
index 0000000..7e53235
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/strlib.cpp
@@ -0,0 +1,252 @@
+/*
+ * File: strlib.cpp
+ * ----------------
+ * This file implements the strlib.h interface.
+ */
+
+#include <cctype>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include "error.h"
+#include "strlib.h"
+using namespace std;
+
+/* Function prototypes */
+
+/*
+ * Implementation notes: numeric conversion
+ * ----------------------------------------
+ * These functions use the <sstream> library to perform the conversion.
+ */
+
+string integerToString(int n) {
+ ostringstream stream;
+ stream << n;
+ return stream.str();
+}
+
+int stringToInteger(string str) {
+ istringstream stream(str);
+ int value;
+ stream >> value >> ws;
+ if (stream.fail() || !stream.eof()) {
+ error("stringToInteger: Illegal integer format (" + str + ")");
+ }
+ return value;
+}
+
+string realToString(double d) {
+ ostringstream stream;
+ stream << uppercase << d;
+ return stream.str();
+}
+
+double stringToReal(string str) {
+ istringstream stream(str);
+ double value;
+ stream >> value >> ws;
+ if (stream.fail() || !stream.eof()) {
+ error("stringToReal: Illegal floating-point format (" + str + ")");
+ }
+ return value;
+}
+
+/*
+ * Implementation notes: case conversion
+ * -------------------------------------
+ * The functions toUpperCase and toLowerCase return a new string whose
+ * characters appear in the desired case. These implementations rely on
+ * the fact that the characters in the string are copied when the
+ * argument is passed to the function, which makes it possible to change
+ * the case of the copy without affecting the original.
+ */
+
+string toUpperCase(string str) {
+ int nChars = str.length();
+ for (int i = 0; i < nChars; i++) {
+ str[i] = toupper(str[i]);
+ }
+ return str;
+}
+
+string toLowerCase(string str) {
+ int nChars = str.length();
+ for (int i = 0; i < nChars; i++) {
+ str[i] = tolower(str[i]);
+ }
+ return str;
+}
+
+/*
+ * Implementation notes: equalsIgnoreCase
+ * --------------------------------------
+ * This implementation uses a for loop to cycle through the characters in
+ * each string. Converting each string to uppercase and then comparing
+ * the results makes for a shorter but less efficient implementation.
+ */
+
+bool equalsIgnoreCase(string s1, string s2) {
+ if (s1.length() != s2.length()) return false;
+ int nChars = s1.length();
+ for (int i = 0; i < nChars; i++) {
+ if (tolower(s1[i]) != tolower(s2[i])) return false;
+ }
+ return true;
+}
+
+/*
+ * Implementation notes: startsWith, endsWith
+ * ------------------------------------------
+ * These implementations are overloaded to allow the second argument to
+ * be either a string or a character.
+ */
+
+bool startsWith(string str, string prefix) {
+ if (str.length() < prefix.length()) return false;
+ int nChars = prefix.length();
+ for (int i = 0; i < nChars; i++) {
+ if (str[i] != prefix[i]) return false;
+ }
+ return true;
+}
+
+bool startsWith(string str, char prefix) {
+ return str.length() > 0 && str[0] == prefix;
+}
+
+bool endsWith(string str, string suffix) {
+ int nChars = suffix.length();
+ int start = str.length() - nChars;
+ if (start < 0) return false;
+ for (int i = 0; i < nChars; i++) {
+ if (str[start + i] != suffix[i]) return false;
+ }
+ return true;
+}
+
+bool endsWith(string str, char suffix) {
+ return str.length() > 0 && str[str.length() - 1] == suffix;
+}
+
+string trim(string str) {
+ int finish = str.length() - 1;
+ while (finish >= 0 && isspace(str[finish])) {
+ finish--;
+ }
+ int start = 0;
+ while (start <= finish && isspace(str[start])) {
+ start++;
+ }
+ return str.substr(start, finish - start + 1);
+}
+
+/*
+ * Implementation notes: readQuotedString and writeQuotedString
+ * ------------------------------------------------------------
+ * Most of the work in these functions has to do with escape sequences.
+ */
+
+static const string STRING_DELIMITERS = ",:)}]\n";
+
+bool stringNeedsQuoting(const string & str) {
+ int n = str.length();
+ for (int i = 0; i < n; i++) {
+ char ch = str[i];
+ if (isspace(ch)) return false;
+ if (STRING_DELIMITERS.find(ch) != string::npos) return true;
+ }
+ return false;
+}
+
+void readQuotedString(istream & is, string & str) {
+ str = "";
+ char ch;
+ while (is.get(ch) && isspace(ch)) {
+ /* Empty */
+ }
+ if (is.fail()) return;
+ if (ch == '\'' || ch == '"') {
+ char delim = ch;
+ while (is.get(ch) && ch != delim) {
+ if (is.fail()) error("Unterminated string");
+ if (ch == '\\') {
+ if (!is.get(ch)) error("Unterminated string");
+ if (isdigit(ch) || ch == 'x') {
+ int maxDigits = 3;
+ int base = 8;
+ if (ch == 'x') {
+ base = 16;
+ maxDigits = 2;
+ }
+ int result = 0;
+ int digit = 0;
+ for (int i = 0; i < maxDigits && ch != delim; i++) {
+ if (isdigit(ch)) {
+ digit = ch - '0';
+ } else if (base == 16 && isxdigit(ch)) {
+ digit = toupper(ch) - 'A' + 10;
+ } else {
+ break;
+ }
+ result = base * result + digit;
+ if (!is.get(ch)) error("Unterminated string");
+ }
+ ch = char(result);
+ is.unget();
+ } else {
+ switch (ch) {
+ case 'a': ch = '\a'; break;
+ case 'b': ch = '\b'; break;
+ case 'f': ch = '\f'; break;
+ case 'n': ch = '\n'; break;
+ case 'r': ch = '\r'; break;
+ case 't': ch = '\t'; break;
+ case 'v': ch = '\v'; break;
+ case '"': ch = '"'; break;
+ case '\'': ch = '\''; break;
+ case '\\': ch = '\\'; break;
+ }
+ }
+ }
+ str += ch;
+ }
+ } else {
+ str += ch;
+ int endTrim = 0;
+ while (is.get(ch) && STRING_DELIMITERS.find(ch) == string::npos) {
+ str += ch;
+ if (!isspace(ch)) endTrim = str.length();
+ }
+ if (is) is.unget();
+ str = str.substr(0, endTrim);
+ }
+}
+
+void writeQuotedString(ostream & os, const string & str, bool forceQuotes) {
+ if (!forceQuotes && stringNeedsQuoting(str)) forceQuotes = true;
+ if (forceQuotes) os << '"';
+ int len = str.length();
+ for (int i = 0; i < len; i++) {
+ char ch = str.at(i);
+ switch (ch) {
+ case '\a': os << "\\a"; break;
+ case '\b': os << "\\b"; break;
+ case '\f': os << "\\f"; break;
+ case '\n': os << "\\n"; break;
+ case '\r': os << "\\r"; break;
+ case '\t': os << "\\t"; break;
+ case '\v': os << "\\v"; break;
+ case '\\': os << "\\\\"; break;
+ default:
+ if (isprint(ch) && ch != '"') {
+ os << ch;
+ } else {
+ ostringstream oss;
+ oss << oct << setw(3) << setfill('0') << (int(ch) & 0xFF);
+ os << "\\" << oss.str();
+ }
+ }
+ }
+ if (forceQuotes) os << '"';
+}
diff --git a/labb8/lib/StanfordCPPLib/strlib.h b/labb8/lib/StanfordCPPLib/strlib.h
new file mode 100755
index 0000000..bb27629
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/strlib.h
@@ -0,0 +1,222 @@
+/*
+ * File: strlib.h
+ * --------------
+ * This file exports several useful string functions that are not
+ * included in the C++ string library.
+ */
+
+#ifndef _strlib_h
+#define _strlib_h
+
+#include <iostream>
+#include <sstream>
+#include <string>
+
+/*
+ * Function: integerToString
+ * Usage: string s = integerToString(n);
+ * -------------------------------------
+ * Converts an integer into the corresponding string of digits.
+ * For example, calling <code>integerToString(123)</code> returns
+ * the string <code>"123"</code>.
+ */
+
+std::string integerToString(int n);
+
+/*
+ * Function: stringToInteger
+ * Usage: int n = stringToInteger(str);
+ * ------------------------------------
+ * Converts a string of digits into an integer. If the string is not a
+ * legal integer or contains extraneous characters other than whitespace,
+ * <code>stringToInteger</code> calls <code>error</code> with an
+ * appropriate message.
+ */
+
+int stringToInteger(std::string str);
+
+/*
+ * Function: realToString
+ * Usage: string s = realToString(d);
+ * ----------------------------------
+ * Converts a floating-point number into the corresponding string form.
+ * For example, calling <code>realToString(23.45)</code> returns
+ * the string <code>"23.45"</code>.
+ */
+
+std::string realToString(double d);
+
+/*
+ * Function: stringToReal
+ * Usage: double d = stringToReal(str);
+ * ------------------------------------
+ * Converts a string representing a real number into its corresponding
+ * value. If the string is not a legal floating-point number or contains
+ * extraneous characters other than whitespace, <code>stringToReal</code>
+ * calls <code>error</code> with an appropriate message.
+ */
+
+double stringToReal(std::string str);
+
+/*
+ * Function: toUpperCase
+ * Usage: string s = toUpperCase(str);
+ * -----------------------------------
+ * Returns a new string in which all lowercase characters have been converted
+ * into their uppercase equivalents.
+ */
+
+std::string toUpperCase(std::string str);
+
+/*
+ * Function: toLowerCase
+ * Usage: string s = toLowerCase(str);
+ * -----------------------------------
+ * Returns a new string in which all uppercase characters have been converted
+ * into their lowercase equivalents.
+ */
+
+std::string toLowerCase(std::string str);
+
+/*
+ * Function: equalsIgnoreCase
+ * Usage: if (equalsIgnoreCase(s1, s2)) ...
+ * ----------------------------------------
+ * Returns <code>true</code> if <code>s1</code> and <code>s2</code> are
+ * equal discounting differences in case.
+ */
+
+bool equalsIgnoreCase(std::string s1, std::string s2);
+
+/*
+ * Function: startsWith
+ * Usage: if (startsWith(str, prefix)) ...
+ * ---------------------------------------
+ * Returns <code>true</code> if the string <code>str</code> starts with
+ * the specified prefix, which may be either a string or a character.
+ */
+
+bool startsWith(std::string str, std::string prefix);
+bool startsWith(std::string str, char prefix);
+
+/*
+ * Function: endsWith
+ * Usage: if (endsWith(str, suffix)) ...
+ * -------------------------------------
+ * Returns <code>true</code> if the string <code>str</code> ends with
+ * the specified suffix, which may be either a string or a character.
+ */
+
+bool endsWith(std::string str, std::string suffix);
+bool endsWith(std::string str, char suffix);
+
+/*
+ * Function: trim
+ * Usage: string trimmed = trim(str);
+ * ----------------------------------
+ * Returns a new string after removing any whitespace characters
+ * from the beginning and end of the argument.
+ */
+
+std::string trim(std::string str);
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+/*
+ * Friend function: writeQuotedString
+ * Usage: writeQuotedString(outfile, str, forceQuotes);
+ * ----------------------------------------------------
+ * Writes the string str to outfile surrounded by double quotes, converting
+ * special characters to escape sequences, as necessary. If the optional
+ * parameter forceQuotes is explicitly set to false, quotes are included
+ * in the output only if necessary.
+ */
+
+void writeQuotedString(std::ostream & os, const std::string & str,
+ bool forceQuotes = true);
+
+/*
+ * Friend function: readQuotedString
+ * Usage: readQuotedString(infile, str);
+ * -------------------------------------
+ * Reads the next string from infile into the reference parameter str.
+ * If the first character (other than whitespace) is either a single
+ * or a double quote, this function reads characters up to the
+ * matching quote, processing standard escape sequences as it goes.
+ * If not, readString reads characters up to any of the characters
+ * in the string STRING_DELIMITERS in the implementation file.
+ */
+
+void readQuotedString(std::istream & is, std::string & str);
+
+/*
+ * Friend function: stringNeedsQuoting
+ * Usage: if (stringNeedsQuoting(str)) ...
+ * ---------------------------------------
+ * Checks whether the string needs quoting in order to be read correctly.
+ */
+
+bool stringNeedsQuoting(const std::string & str);
+
+/*
+ * Friend function: writeGenericValue
+ * Usage: writeGenericValue(os, value, forceQuotes);
+ * -------------------------------------------------
+ * Writes a generic value to the output stream. If that value is a string,
+ * this function uses writeQuotedString to write the value.
+ */
+
+template <typename ValueType>
+void writeGenericValue(std::ostream & os, const ValueType & value,
+ bool) {
+ os << value;
+}
+
+template <>
+inline void writeGenericValue(std::ostream & os, const std::string & value,
+ bool forceQuotes) {
+ writeQuotedString(os, value, forceQuotes);
+}
+
+template <typename ValueType>
+inline std::string genericValueToString(const ValueType & value,
+ bool forceQuotes = false) {
+ std::ostringstream os;
+ writeGenericValue(os, value, forceQuotes);
+ return os.str();
+}
+
+template <>
+inline std::string genericValueToString(const std::string & value,
+ bool forceQuotes) {
+ std::ostringstream os;
+ writeQuotedString(os, value, forceQuotes);
+ return os.str();
+}
+
+
+/*
+ * Friend function: readGenericValue
+ * Usage: readGenericValue(is, value);
+ * -----------------------------------
+ * Reads a generic value from the input stream. If that value is a string,
+ * this function uses readQuotedString to read the value.
+ */
+
+template <typename ValueType>
+void readGenericValue(std::istream & is, ValueType & value) {
+ is >> value;
+}
+
+template <>
+inline void readGenericValue(std::istream & is, std::string & value) {
+ readQuotedString(is, value);
+}
+
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/tokenscanner.cpp b/labb8/lib/StanfordCPPLib/tokenscanner.cpp
new file mode 100755
index 0000000..6dadd0e
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/tokenscanner.cpp
@@ -0,0 +1,411 @@
+/*
+ * File: tokenscanner.cpp
+ * ----------------------
+ * Implementation for the TokenScanner class.
+ */
+
+#include <cctype>
+#include <iostream>
+#include "error.h"
+#include "tokenscanner.h"
+#include "strlib.h"
+#include "stack.h"
+using namespace std;
+
+TokenScanner::TokenScanner() {
+ initScanner();
+ setInput("");
+}
+
+TokenScanner::TokenScanner(string str) {
+ initScanner();
+ setInput(str);
+}
+
+TokenScanner::TokenScanner(istream & infile) {
+ initScanner();
+ setInput(infile);
+}
+
+TokenScanner::~TokenScanner() {
+ if (stringInputFlag) delete isp;
+}
+
+void TokenScanner::setInput(string str) {
+ stringInputFlag = true;
+ buffer = str;
+ isp = new istringstream(buffer);
+ savedTokens = NULL;
+}
+
+void TokenScanner::setInput(istream & infile) {
+ stringInputFlag = false;
+ isp = &infile;
+ savedTokens = NULL;
+}
+
+bool TokenScanner::hasMoreTokens() {
+ string token = nextToken();
+ saveToken(token);
+ return (token != "");
+}
+
+string TokenScanner::nextToken() {
+ if (savedTokens != NULL) {
+ StringCell *cp = savedTokens;
+ string token = cp->str;
+ savedTokens = cp->link;
+ delete cp;
+ return token;
+ }
+ while (true) {
+ if (ignoreWhitespaceFlag) skipSpaces();
+ int ch = isp->get();
+ if (ch == '/' && ignoreCommentsFlag) {
+ ch = isp->get();
+ if (ch == '/') {
+ while (true) {
+ ch = isp->get();
+ if (ch == '\n' || ch == '\r' || ch == EOF) break;
+ }
+ continue;
+ } else if (ch == '*') {
+ int prev = EOF;
+ while (true) {
+ ch = isp->get();
+ if (ch == EOF || (prev == '*' && ch == '/')) break;
+ prev = ch;
+ }
+ continue;
+ }
+ if (ch != EOF) isp->unget();
+ ch = '/';
+ }
+ if (ch == EOF) return "";
+ if ((ch == '"' || ch == '\'') && scanStringsFlag) {
+ isp->unget();
+ return scanString();
+ }
+ if (isdigit(ch) && scanNumbersFlag) {
+ isp->unget();
+ return scanNumber();
+ }
+ if (isWordCharacter(ch)) {
+ isp->unget();
+ return scanWord();
+ }
+ string op = string(1, ch);
+ while (isOperatorPrefix(op)) {
+ ch = isp->get();
+ if (ch == EOF) break;
+ op += ch;
+ }
+ while (op.length() > 1 && !isOperator(op)) {
+ isp->unget();
+ op.erase(op.length() - 1, 1);
+ }
+ return op;
+ }
+}
+
+void TokenScanner::saveToken(string token) {
+ StringCell *cp = new StringCell;
+ cp->str = token;
+ cp->link = savedTokens;
+ savedTokens = cp;
+}
+
+void TokenScanner::ignoreWhitespace() {
+ ignoreWhitespaceFlag = true;
+}
+
+void TokenScanner::ignoreComments() {
+ ignoreCommentsFlag = true;
+}
+
+void TokenScanner::scanNumbers() {
+ scanNumbersFlag = true;
+}
+
+void TokenScanner::scanStrings() {
+ scanStringsFlag = true;
+}
+
+void TokenScanner::addWordCharacters(string str) {
+ wordChars += str;
+}
+
+void TokenScanner::addOperator(string op) {
+ StringCell *cp = new StringCell;
+ cp->str = op;
+ cp->link = operators;
+ operators = cp;
+}
+
+int TokenScanner::getPosition() const {
+ if (savedTokens == NULL) {
+ return int(isp->tellg());
+ } else {
+ return int(isp->tellg()) - savedTokens->str.length();
+ }
+ return -1;
+}
+
+bool TokenScanner::isWordCharacter(char ch) const {
+ return isalnum(ch) || wordChars.find(ch) != string::npos;
+};
+
+void TokenScanner::verifyToken(string expected) {
+ string token = nextToken();
+ if (token != expected) {
+ string msg = "Found \"" + token + "\"" +
+ " when expecting \"" + expected + "\"";
+ error(msg);
+ }
+};
+
+TokenType TokenScanner::getTokenType(string token) const {
+ if (token == "") return TokenType(EOF);
+ char ch = token[0];
+ if (isspace(ch)) return SEPARATOR;
+ if (ch == '"' || (ch == '\'' && token.length() > 1)) return STRING;
+ if (isdigit(ch)) return NUMBER;
+ if (isWordCharacter(ch)) return WORD;
+ return OPERATOR;
+};
+
+string TokenScanner::getStringValue(string token) const {
+ string str = "";
+ int start = 0;
+ int finish = token.length();
+ if (finish > 1 && (token[0] == '"' || token[0] == '\'')) {
+ start = 1;
+ finish--;
+ }
+ for (int i = start; i < finish; i++) {
+ char ch = token[i];
+ if (ch == '\\') {
+ ch = token[++i];
+ if (isdigit(ch) || ch == 'x') {
+ int base = 8;
+ if (ch == 'x') {
+ base = 16;
+ i++;
+ }
+ int result = 0;
+ int digit = 0;
+ while (i < finish) {
+ ch = token[i];
+ if (isdigit(ch)) {
+ digit = ch - '0';
+ } else if (isalpha(ch)) {
+ digit = toupper(ch) - 'A' + 10;
+ } else {
+ digit = base;
+ }
+ if (digit >= base) break;
+ result = base * result + digit;
+ i++;
+ }
+ ch = char(result);
+ i--;
+ } else {
+ switch (ch) {
+ case 'a': ch = '\a'; break;
+ case 'b': ch = '\b'; break;
+ case 'f': ch = '\f'; break;
+ case 'n': ch = '\n'; break;
+ case 'r': ch = '\r'; break;
+ case 't': ch = '\t'; break;
+ case 'v': ch = '\v'; break;
+ case '"': ch = '"'; break;
+ case '\'': ch = '\''; break;
+ case '\\': ch = '\\'; break;
+ }
+ }
+ }
+ str += ch;
+ }
+ return str;
+}
+
+int TokenScanner::getChar() {
+ return isp->get();
+}
+
+void TokenScanner::ungetChar(int) {
+ isp->unget();
+}
+
+/* Private methods */
+
+void TokenScanner::initScanner() {
+ ignoreWhitespaceFlag = false;
+ ignoreCommentsFlag = false;
+ scanNumbersFlag = false;
+ scanStringsFlag = false;
+ operators = NULL;
+}
+
+/*
+ * Implementation notes: skipSpaces
+ * --------------------------------
+ * Advances the position of the scanner until the current character is
+ * not a whitespace character.
+ */
+
+void TokenScanner::skipSpaces() {
+ while (true) {
+ int ch = isp->get();
+ if (ch == EOF) return;
+ if (!isspace(ch)) {
+ isp->unget();
+ return;
+ }
+ }
+}
+
+/*
+ * Implementation notes: scanWord
+ * ------------------------------
+ * Reads characters until the scanner reaches the end of a sequence
+ * of word characters.
+ */
+
+string TokenScanner::scanWord() {
+ string token = "";
+ while (true) {
+ int ch = isp->get();
+ if (ch == EOF) break;
+ if (!isWordCharacter(ch)) {
+ isp->unget();
+ break;
+ }
+ token += char(ch);
+ }
+ return token;
+}
+
+/*
+ * Implementation notes: scanNumber
+ * --------------------------------
+ * Reads characters until the scanner reaches the end of a legal number.
+ * The function operates by simulating what computer scientists
+ * call a finite-state machine. The program uses the variable
+ * <code>state</code> to record the history of the process and
+ * determine what characters would be legal at this point in time.
+ */
+
+string TokenScanner::scanNumber() {
+ string token = "";
+ NumberScannerState state = INITIAL_STATE;
+ while (state != FINAL_STATE) {
+ int ch = isp->get();
+ switch (state) {
+ case INITIAL_STATE:
+ if (!isdigit(ch)) {
+ error("Internal error: illegal call to scanNumber");
+ }
+ state = BEFORE_DECIMAL_POINT;
+ break;
+ case BEFORE_DECIMAL_POINT:
+ if (ch == '.') {
+ state = AFTER_DECIMAL_POINT;
+ } else if (ch == 'E' || ch == 'e') {
+ state = STARTING_EXPONENT;
+ } else if (!isdigit(ch)) {
+ if (ch != EOF) isp->unget();
+ state = FINAL_STATE;
+ }
+ break;
+ case AFTER_DECIMAL_POINT:
+ if (ch == 'E' || ch == 'e') {
+ state = STARTING_EXPONENT;
+ } else if (!isdigit(ch)) {
+ if (ch != EOF) isp->unget();
+ state = FINAL_STATE;
+ }
+ break;
+ case STARTING_EXPONENT:
+ if (ch == '+' || ch == '-') {
+ state = FOUND_EXPONENT_SIGN;
+ } else if (isdigit(ch)) {
+ state = SCANNING_EXPONENT;
+ } else {
+ if (ch != EOF) isp->unget();
+ isp->unget();
+ state = FINAL_STATE;
+ }
+ break;
+ case FOUND_EXPONENT_SIGN:
+ if (isdigit(ch)) {
+ state = SCANNING_EXPONENT;
+ } else {
+ if (ch != EOF) isp->unget();
+ isp->unget();
+ isp->unget();
+ state = FINAL_STATE;
+ }
+ break;
+ case SCANNING_EXPONENT:
+ if (!isdigit(ch)) {
+ if (ch != EOF) isp->unget();
+ state = FINAL_STATE;
+ }
+ break;
+ default:
+ state = FINAL_STATE;
+ break;
+ }
+ if (state != FINAL_STATE) {
+ token += char(ch);
+ }
+ }
+ return token;
+}
+
+/*
+ * Implementation notes: scanString
+ * --------------------------------
+ * Reads and returns a quoted string from the scanner, continuing until
+ * it scans the matching delimiter. The scanner generates an error if
+ * there is no closing quotation mark before the end of the input.
+ */
+
+string TokenScanner::scanString() {
+ string token = "";
+ char delim = isp->get();
+ token += delim;
+ bool escape = false;
+ while (true) {
+ int ch = isp->get();
+ if (ch == EOF) error("TokenScanner found unterminated string");
+ if (ch == delim && !escape) break;
+ escape = (ch == '\\') && !escape;
+ token += ch;
+ }
+ return token + delim;
+}
+
+/*
+ * Implementation notes: isOperator, isOperatorPrefix
+ * --------------------------------------------------
+ * These methods search the list of operators and return true if the
+ * specified operator is either in the list or a prefix of an operator
+ * in the list, respectively. This code could be made considerably more
+ * efficient by implementing operators as a trie.
+ */
+
+bool TokenScanner::isOperator(string op) {
+ for (StringCell *cp = operators; cp != NULL; cp = cp->link) {
+ if (op == cp->str) return true;
+ }
+ return false;
+}
+
+bool TokenScanner::isOperatorPrefix(string op) {
+ for (StringCell *cp = operators; cp != NULL; cp = cp->link) {
+ if (startsWith(cp->str, op)) return true;
+ }
+ return false;
+}
diff --git a/labb8/lib/StanfordCPPLib/tokenscanner.h b/labb8/lib/StanfordCPPLib/tokenscanner.h
new file mode 100755
index 0000000..0b2eb32
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/tokenscanner.h
@@ -0,0 +1,351 @@
+/*
+ * File: tokenscanner.h
+ * --------------------
+ * This file exports a <code>TokenScanner</code> class that divides
+ * a string into individual logical units called <b><i>tokens</i></b>.
+ */
+
+#ifndef _tokenscanner_h
+#define _tokenscanner_h
+
+#include <iostream>
+#include <string>
+#include "private/tokenpatch.h"
+
+/*
+ * Type: TokenType
+ * ---------------
+ * This enumerated type defines the values of the
+ * <code>getTokenType</code> method.
+ */
+
+#ifdef _WIN32
+# define TokenType TokenTypeT
+# define WORD WORD_TC
+#endif
+
+enum TokenType { SEPARATOR, WORD, NUMBER, STRING, OPERATOR };
+
+/*
+ * Class: TokenScanner
+ * -------------------
+ * This class divides a string into individual tokens. The typical
+ * use of the <code>TokenScanner</code> class is illustrated by the
+ * following pattern, which reads the tokens in the string variable
+ * <code>input</code>:
+ *
+ *<pre>
+ * TokenScanner scanner(input);
+ * while (scanner.hasMoreTokens()) {
+ * string token = scanner.nextToken();
+ * ... process the token ...
+ * }
+ *</pre>
+ *
+ * The <code>TokenScanner</code> class exports several additional methods
+ * that give clients more control over its behavior. Those methods are
+ * described individually in the documentation.
+ */
+
+class TokenScanner {
+
+public:
+
+/*
+ * Constructor: TokenScanner
+ * Usage: TokenScanner scanner;
+ * TokenScanner scanner(str);
+ * TokenScanner scanner(infile);
+ * ------------------------------------
+ * Initializes a scanner object. The initial token stream comes from
+ * the specified string or input stream, if supplied. The default
+ * constructor creates a scanner with an empty token stream.
+ */
+
+ TokenScanner();
+ TokenScanner(std::string str);
+ TokenScanner(std::istream & infile);
+
+/*
+ * Destructor: ~TokenScanner
+ * -------------------------
+ * Deallocates the storage associated with this scanner.
+ */
+
+ virtual ~TokenScanner();
+
+/*
+ * Method: setInput
+ * Usage: scanner.setInput(str);
+ * scanner.setInput(infile);
+ * --------------------------------
+ * Sets the token stream for this scanner to the specified string or
+ * input stream. Any previous token stream is discarded.
+ */
+
+ void setInput(std::string str);
+ void setInput(std::istream & infile);
+
+/*
+ * Method: hasMoreTokens
+ * Usage: if (scanner.hasMoreTokens()) ...
+ * ---------------------------------------
+ * Returns <code>true</code> if there are additional tokens for this
+ * scanner to read.
+ */
+
+ bool hasMoreTokens();
+
+/*
+ * Method: nextToken
+ * Usage: token = scanner.nextToken();
+ * -----------------------------------
+ * Returns the next token from this scanner. If <code>nextToken</code>
+ * is called when no tokens are available, it returns the empty string.
+ */
+
+ std::string nextToken();
+
+/*
+ * Method: saveToken
+ * Usage: scanner.saveToken(token);
+ * --------------------------------
+ * Pushes the specified token back into this scanner's input stream.
+ * On the next call to <code>nextToken</code>, the scanner will return
+ * the saved token without reading any additional characters from the
+ * token stream.
+ */
+
+ void saveToken(std::string token);
+
+/*
+ * Method: getPosition
+ * Usage: int pos = scanner.getPosition();
+ * ---------------------------------------
+ * Returns the current position of the scanner in the input stream.
+ * If <code>saveToken</code> has been called, this position corresponds
+ * to the beginning of the saved token. If <code>saveToken</code> is
+ * called more than once, <code>getPosition</code> returns -1.
+ */
+
+ int getPosition() const;
+
+/*
+ * Method: ignoreWhitespace
+ * Usage: scanner.ignoreWhitespace();
+ * ----------------------------------
+ * Tells the scanner to ignore whitespace characters. By default,
+ * the <code>nextToken</code> method treats whitespace characters
+ * (typically spaces and tabs) just like any other punctuation mark
+ * and returns them as single-character tokens.
+ * Calling
+ *
+ *<pre>
+ * scanner.ignoreWhitespace();
+ *</pre>
+ *
+ * changes this behavior so that the scanner ignore whitespace characters.
+ */
+
+ void ignoreWhitespace();
+
+/*
+ * Method: ignoreComments
+ * Usage: scanner.ignoreComments();
+ * --------------------------------
+ * Tells the scanner to ignore comments. The scanner package recognizes
+ * both the slash-star and slash-slash comment format from the C-based
+ * family of languages. Calling
+ *
+ *<pre>
+ * scanner.ignoreComments();
+ *</pre>
+ *
+ * sets the parser to ignore comments.
+ */
+
+ void ignoreComments();
+
+/*
+ * Method: scanNumbers
+ * Usage: scanner.scanNumbers();
+ * -----------------------------
+ * Controls how the scanner treats tokens that begin with a digit. By
+ * default, the <code>nextToken</code> method treats numbers and letters
+ * identically and therefore does not provide any special processing for
+ * numbers. Calling
+ *
+ *<pre>
+ * scanner.scanNumbers();
+ *</pre>
+ *
+ * changes this behavior so that <code>nextToken</code> returns the
+ * longest substring that can be interpreted as a real number.
+ */
+
+ void scanNumbers();
+
+/*
+ * Method: scanStrings
+ * Usage: scanner.scanStrings();
+ * -----------------------------
+ * Controls how the scanner treats tokens enclosed in quotation marks. By
+ * default, quotation marks (either single or double) are treated just like
+ * any other punctuation character. Calling
+ *
+ *<pre>
+ * scanner.scanStrings();
+ *</pre>
+ *
+ * changes this assumption so that <code>nextToken</code> returns a single
+ * token consisting of all characters through the matching quotation mark.
+ * The quotation marks are returned as part of the scanned token so that
+ * clients can differentiate strings from other token types.
+ */
+
+ void scanStrings();
+
+/*
+ * Method: addWordCharacters
+ * Usage: scanner.addWordCharacters(str);
+ * --------------------------------------
+ * Adds the characters in <code>str</code> to the set of characters
+ * legal in a <code>WORD</code> token. For example, calling
+ * <code>addWordCharacters("_")</code> adds the underscore to the
+ * set of characters that are accepted as part of a word.
+ */
+
+ void addWordCharacters(std::string str);
+
+/*
+ * Method: isWordCharacter
+ * Usage: if (scanner.isWordCharacter(ch)) ...
+ * -------------------------------------------
+ * Returns <code>true</code> if the character is valid in a word.
+ */
+
+ bool isWordCharacter(char ch) const;
+
+/*
+ * Method: addOperator
+ * Usage: scanner.addOperator(op);
+ * -------------------------------
+ * Defines a new multicharacter operator. Whenever you call
+ * <code>nextToken</code> when the input stream contains operator
+ * characters, the scanner returns the longest possible operator
+ * string that can be read at that point.
+ */
+
+ void addOperator(std::string op);
+
+/*
+ * Method: verifyToken
+ * Usage: scanner.verifyToken(expected);
+ * -------------------------------------
+ * Reads the next token and makes sure it matches the string
+ * <code>expected</code>. If it does not, <code>verifyToken</code>
+ * throws an error.
+ */
+
+ void verifyToken(std::string expected);
+
+/*
+ * Method: getTokenType
+ * Usage: TokenType type = scanner.getTokenType(token);
+ * ----------------------------------------------------
+ * Returns the type of this token. This type will match one of the
+ * following enumerated type constants: <code>EOF</code>,
+ * <code>SEPARATOR</code>, <code>WORD</code>, <code>NUMBER</code>,
+ * <code>STRING</code>, or <code>OPERATOR</code>.
+ */
+
+TokenType getTokenType(std::string token) const;
+
+/*
+ * Method: getChar
+ * Usage: int ch = scanner.getChar();
+ * ----------------------------------
+ * Reads the next character from the scanner input stream.
+ */
+
+int getChar();
+
+/*
+ * Method: ungetChar
+ * Usage: scanner.ungetChar(ch);
+ * -----------------------------
+ * Pushes the character <code>ch</code> back into the scanner stream.
+ * The character must match the one that was read.
+ */
+
+void ungetChar(int ch);
+
+/*
+ * Method: getStringValue
+ * Usage: string str = scanner.getStringValue(token);
+ * --------------------------------------------------
+ * Returns the string value of a token. This value is formed by removing
+ * any surrounding quotation marks and replacing escape sequences by the
+ * appropriate characters.
+ */
+
+ std::string getStringValue(std::string token) const;
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+private:
+
+/*
+ * Private type: StringCell
+ * ------------------------
+ * This type is used to construct linked lists of cells, which are used
+ * to represent both the stack of saved tokens and the set of defined
+ * operators. These types cannot use the Stack and Lexicon classes
+ * directly because tokenscanner.h is an extremely low-level interface,
+ * and doing so would create circular dependencies in the .h files.
+ */
+
+ struct StringCell {
+ std::string str;
+ StringCell *link;
+ };
+
+ enum NumberScannerState {
+ INITIAL_STATE,
+ BEFORE_DECIMAL_POINT,
+ AFTER_DECIMAL_POINT,
+ STARTING_EXPONENT,
+ FOUND_EXPONENT_SIGN,
+ SCANNING_EXPONENT,
+ FINAL_STATE
+ };
+
+ std::string buffer; /* The original argument string */
+ std::istream *isp; /* The input stream for tokens */
+ bool stringInputFlag; /* Flag indicating string input */
+ bool ignoreWhitespaceFlag; /* Scanner ignores whitespace */
+ bool ignoreCommentsFlag; /* Scanner ignores comments */
+ bool scanNumbersFlag; /* Scanner parses numbers */
+ bool scanStringsFlag; /* Scanner parses strings */
+ std::string wordChars; /* Additional word characters */
+ StringCell *savedTokens; /* Stack of saved tokens */
+ StringCell *operators; /* List of multichar operators */
+
+/* Private method prototypes */
+
+ void initScanner();
+ void skipSpaces();
+ std::string scanWord();
+ std::string scanNumber();
+ std::string scanString();
+ bool isOperator(std::string op);
+ bool isOperatorPrefix(std::string op);
+
+};
+
+#endif
diff --git a/labb8/lib/StanfordCPPLib/vector.h b/labb8/lib/StanfordCPPLib/vector.h
new file mode 100755
index 0000000..9781daa
--- /dev/null
+++ b/labb8/lib/StanfordCPPLib/vector.h
@@ -0,0 +1,727 @@
+/*
+ * File: vector.h
+ * --------------
+ * This file exports the <code>Vector</code> class, which provides an
+ * efficient, safe, convenient replacement for the array type in C++.
+ */
+
+#ifndef _vector_h
+#define _vector_h
+
+#include <iterator>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include "foreach.h"
+#include "strlib.h"
+
+/*
+ * Class: Vector<ValueType>
+ * ------------------------
+ * This class stores an ordered list of values similar to an array.
+ * It supports traditional array selection using square brackets, but
+ * also supports inserting and deleting elements. It is similar in
+ * function to the STL <code>vector</code> type, but is simpler both
+ * to use and to implement.
+ */
+
+template <typename ValueType>
+class Vector {
+
+public:
+
+/*
+ * Constructor: Vector
+ * Usage: Vector<ValueType> vec;
+ * Vector<ValueType> vec(n, value);
+ * ---------------------------------------
+ * Initializes a new vector. The default constructor creates an
+ * empty vector. The second form creates an array with <code>n</code>
+ * elements, each of which is initialized to <code>value</code>;
+ * if <code>value</code> is missing, the elements are initialized
+ * to the default value for the type.
+ */
+
+ Vector();
+ explicit Vector(int n, ValueType value = ValueType());
+
+/*
+ * Destructor: ~Vector
+ * -------------------
+ * Frees any heap storage allocated by this vector.
+ */
+
+ virtual ~Vector();
+
+/*
+ * Method: size
+ * Usage: int nElems = vec.size();
+ * -------------------------------
+ * Returns the number of elements in this vector.
+ */
+
+ int size() const;
+
+/*
+ * Method: isEmpty
+ * Usage: if (vec.isEmpty()) ...
+ * -----------------------------
+ * Returns <code>true</code> if this vector contains no elements.
+ */
+
+ bool isEmpty() const;
+
+/*
+ * Method: clear
+ * Usage: vec.clear();
+ * -------------------
+ * Removes all elements from this vector.
+ */
+
+ void clear();
+
+/*
+ * Method: get
+ * Usage: ValueType val = vec.get(index);
+ * --------------------------------------
+ * Returns the element at the specified index in this vector. This
+ * method signals an error if the index is not in the array range.
+ */
+
+ const ValueType & get(int index) const;
+
+/*
+ * Method: set
+ * Usage: vec.set(index, value);
+ * -----------------------------
+ * Replaces the element at the specified index in this vector with
+ * a new value. The previous value at that index is overwritten.
+ * This method signals an error if the index is not in the array range.
+ */
+
+ void set(int index, const ValueType & value);
+
+/*
+ * Method: insert
+ * Usage: vec.insert(0, value);
+ * ----------------------------
+ * Inserts the element into this vector before the specified index.
+ * All subsequent elements are shifted one position to the right. This
+ * method signals an error if the index is outside the range from 0
+ * up to and including the length of the vector.
+ */
+
+ void insert(int index, ValueType value);
+
+/*
+ * Method: remove
+ * Usage: vec.remove(index);
+ * -------------------------
+ * Removes the element at the specified index from this vector.
+ * All subsequent elements are shifted one position to the left. This
+ * method signals an error if the index is outside the array range.
+ */
+
+ void remove(int index);
+
+/*
+ * Method: add
+ * Usage: vec.add(value);
+ * ----------------------
+ * Adds a new value to the end of this vector. To ensure compatibility
+ * with the <code>vector</code> class in the Standard Template Library,
+ * this method is also called <code>push_back</code>.
+ */
+
+ void add(ValueType value);
+ void push_back(ValueType value);
+
+/*
+ * Operator: []
+ * Usage: vec[index]
+ * -----------------
+ * Overloads <code>[]</code> to select elements from this vector.
+ * This extension enables the use of traditional array notation to
+ * get or set individual elements. This method signals an error if
+ * the index is outside the array range. The file supports two
+ * versions of this operator, one for <code>const</code> vectors and
+ * one for mutable vectors.
+ */
+
+ ValueType & operator[](int index);
+ const ValueType & operator[](int index) const;
+
+/*
+ * Operator: +
+ * Usage: v1 + v2
+ * --------------
+ * Concatenates two vectors.
+ */
+
+ Vector operator+(const Vector & v2) const;
+
+/*
+ * Operator: +=
+ * Usage: v1 += v2;
+ * v1 += value;
+ * -------------------
+ * Adds all of the elements from <code>v2</code> (or the single
+ * specified value) to <code>v1</code>. As a convenience, the
+ * <code>Vector</code> package also overloads the comma operator so
+ * that it is possible to initialize a vector like this:
+ *
+ *<pre>
+ * Vector&lt;int&gt; digits;
+ * digits += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
+ *</pre>
+ */
+
+ Vector & operator+=(const Vector & v2);
+ Vector & operator+=(const ValueType & value);
+
+ bool operator==(const Vector & v2);
+ bool operator!=(const Vector & v2);
+
+/*
+ * Method: toString
+ * Usage: string str = vec.toString();
+ * -----------------------------------
+ * Converts the vector to a printable string representation.
+ */
+
+ std::string toString();
+
+/*
+ * Method: mapAll
+ * Usage: vec.mapAll(fn);
+ * ----------------------
+ * Calls the specified function on each element of the vector in
+ * ascending index order.
+ */
+
+ void mapAll(void (*fn)(ValueType)) const;
+ void mapAll(void (*fn)(const ValueType &)) const;
+
+ template <typename FunctorType>
+ void mapAll(FunctorType fn) const;
+
+/*
+ * Additional Vector operations
+ * ----------------------------
+ * In addition to the methods listed in this interface, the Vector
+ * class supports the following operations:
+ *
+ * - Stream I/O using the << and >> operators
+ * - Deep copying for the copy constructor and assignment operator
+ * - Iteration using the range-based for statement or STL iterators
+ *
+ * The iteration forms process the Vector in index order.
+ */
+
+/* Private section */
+
+/**********************************************************************/
+/* Note: Everything below this point in the file is logically part */
+/* of the implementation and should not be of interest to clients. */
+/**********************************************************************/
+
+private:
+
+/*
+ * Implementation notes: Vector data structure
+ * -------------------------------------------
+ * The elements of the Vector are stored in a dynamic array of
+ * the specified element type. If the space in the array is ever
+ * exhausted, the implementation doubles the array capacity.
+ */
+
+/* Instance variables */
+
+ ValueType *elements; /* A dynamic array of the elements */
+ int capacity; /* The allocated size of the array */
+ int count; /* The number of elements in use */
+
+/* Private methods */
+
+ void expandCapacity();
+ void deepCopy(const Vector & src);
+
+/*
+ * Hidden features
+ * ---------------
+ * The remainder of this file consists of the code required to
+ * support deep copying and iteration. Including these methods
+ * in the public interface would make that interface more
+ * difficult to understand for the average client.
+ */
+
+public:
+
+/*
+ * Deep copying support
+ * --------------------
+ * This copy constructor and operator= are defined to make a deep copy,
+ * making it possible to pass or return vectors by value and assign
+ * from one vector to another.
+ */
+
+ Vector(const Vector & src);
+ Vector & operator=(const Vector & src);
+
+/*
+ * Operator: ,
+ * -----------
+ * Adds an element to the vector passed as the left-hand operatand.
+ * This form makes it easier to initialize vectors in old versions of C++.
+ */
+
+ Vector & operator,(const ValueType & value);
+
+/*
+ * Iterator support
+ * ----------------
+ * The classes in the StanfordCPPLib collection implement input
+ * iterators so that they work symmetrically with respect to the
+ * corresponding STL classes.
+ */
+
+ class iterator :
+ public std::iterator<std::random_access_iterator_tag, ValueType> {
+
+ private:
+ const Vector *vp;
+ int index;
+
+ public:
+
+ iterator() {
+ this->vp = NULL;
+ }
+
+ iterator(const iterator & it) {
+ this->vp = it.vp;
+ this->index = it.index;
+ }
+
+ iterator(const Vector *vp, int index) {
+ this->vp = vp;
+ this->index = index;
+ }
+
+ iterator & operator++() {
+ index++;
+ return *this;
+ }
+
+ iterator operator++(int) {
+ iterator copy(*this);
+ operator++();
+ return copy;
+ }
+
+ iterator & operator--() {
+ index--;
+ return *this;
+ }
+
+ iterator operator--(int) {
+ iterator copy(*this);
+ operator--();
+ return copy;
+ }
+
+ bool operator==(const iterator & rhs) {
+ return vp == rhs.vp && index == rhs.index;
+ }
+
+ bool operator!=(const iterator & rhs) {
+ return !(*this == rhs);
+ }
+
+ bool operator<(const iterator & rhs) {
+ extern void error(std::string msg);
+ if (vp != rhs.vp) error("Iterators are in different vectors");
+ return index < rhs.index;
+ }
+
+ bool operator<=(const iterator & rhs) {
+ extern void error(std::string msg);
+ if (vp != rhs.vp) error("Iterators are in different vectors");
+ return index <= rhs.index;
+ }
+
+ bool operator>(const iterator & rhs) {
+ extern void error(std::string msg);
+ if (vp != rhs.vp) error("Iterators are in different vectors");
+ return index > rhs.index;
+ }
+
+ bool operator>=(const iterator & rhs) {
+ extern void error(std::string msg);
+ if (vp != rhs.vp) error("Iterators are in different vectors");
+ return index >= rhs.index;
+ }
+
+ iterator operator+(const int & rhs) {
+ return iterator(vp, index + rhs);
+ }
+
+ iterator operator+=(const int & rhs) {
+ index += rhs;
+ return *this;
+ }
+
+ iterator operator-(const int & rhs) {
+ return iterator(vp, index - rhs);
+ }
+
+ iterator operator-=(const int & rhs) {
+ index -= rhs;
+ return *this;
+ }
+
+ int operator-(const iterator & rhs) {
+ extern void error(std::string msg);
+ if (vp != rhs.vp) error("Iterators are in different vectors");
+ return index - rhs.index;
+ }
+
+ ValueType & operator*() {
+ return vp->elements[index];
+ }
+
+ ValueType *operator->() {
+ return &vp->elements[index];
+ }
+
+ ValueType & operator[](int k) {
+ return vp->elements[index + k];
+ }
+
+ };
+
+ iterator begin() const {
+ return iterator(this, 0);
+ }
+
+ iterator end() const {
+ return iterator(this, count);
+ }
+
+};
+
+/* Implementation section */
+
+extern void error(std::string msg);
+
+/*
+ * Implementation notes: Vector constructor and destructor
+ * -------------------------------------------------------
+ * The constructor allocates storage for the dynamic array
+ * and initializes the other fields of the object. The
+ * destructor frees the memory used for the array.
+ */
+
+template <typename ValueType>
+Vector<ValueType>::Vector() {
+ count = capacity = 0;
+ elements = NULL;
+}
+
+template <typename ValueType>
+Vector<ValueType>::Vector(int n, ValueType value) {
+ count = capacity = n;
+ elements = (n == 0) ? NULL : new ValueType[n];
+ for (int i = 0; i < n; i++) {
+ elements[i] = value;
+ }
+}
+
+template <typename ValueType>
+Vector<ValueType>::~Vector() {
+ if (elements != NULL) delete[] elements;
+}
+
+/*
+ * Implementation notes: Vector methods
+ * ------------------------------------
+ * The basic Vector methods are straightforward and should require
+ * no detailed documentation.
+ */
+
+template <typename ValueType>
+int Vector<ValueType>::size() const {
+ return count;
+}
+
+template <typename ValueType>
+bool Vector<ValueType>::isEmpty() const {
+ return count == 0;
+}
+
+template <typename ValueType>
+void Vector<ValueType>::clear() {
+ if (elements != NULL) delete[] elements;
+ count = capacity = 0;
+ elements = NULL;
+}
+
+template <typename ValueType>
+const ValueType & Vector<ValueType>::get(int index) const {
+ if (index < 0 || index >= count) error("get: index out of range");
+ return elements[index];
+}
+
+template <typename ValueType>
+void Vector<ValueType>::set(int index, const ValueType & value) {
+ if (index < 0 || index >= count) error("set: index out of range");
+ elements[index] = value;
+}
+
+/*
+ * Implementation notes: insert, remove, add
+ * -----------------------------------------
+ * These methods must shift the existing elements in the array to
+ * make room for a new element or to close up the space left by a
+ * deleted one.
+ */
+
+template <typename ValueType>
+void Vector<ValueType>::insert(int index, ValueType value) {
+ if (count == capacity) expandCapacity();
+ if (index < 0 || index > count) {
+ error("insert: index out of range");
+ }
+ for (int i = count; i > index; i--) {
+ elements[i] = elements[i - 1];
+ }
+ elements[index] = value;
+ count++;
+}
+
+template <typename ValueType>
+void Vector<ValueType>::remove(int index) {
+ if (index < 0 || index >= count) error("remove: index out of range");
+ for (int i = index; i < count - 1; i++) {
+ elements[i] = elements[i + 1];
+ }
+ count--;
+}
+
+template <typename ValueType>
+void Vector<ValueType>::add(ValueType value) {
+ insert(count, value);
+}
+
+template <typename ValueType>
+void Vector<ValueType>::push_back(ValueType value) {
+ insert(count, value);
+}
+
+/*
+ * Implementation notes: Vector selection
+ * --------------------------------------
+ * The following code implements traditional array selection using
+ * square brackets for the index.
+ */
+
+template <typename ValueType>
+ValueType & Vector<ValueType>::operator[](int index) {
+ if (index < 0 || index >= count) error("Selection index out of range");
+ return elements[index];
+}
+template <typename ValueType>
+const ValueType & Vector<ValueType>::operator[](int index) const {
+ if (index < 0 || index >= count) error("Selection index out of range");
+ return elements[index];
+}
+
+template <typename ValueType>
+Vector<ValueType> Vector<ValueType>::operator+(const Vector & v2) const {
+ Vector<ValueType> vec = *this;
+ foreach (ValueType value in v2) {
+ vec.add(value);
+ }
+ return vec;
+}
+
+template <typename ValueType>
+Vector<ValueType> & Vector<ValueType>::operator+=(const Vector & v2) {
+ foreach (ValueType value in v2) {
+ *this += value;
+ }
+ return *this;
+}
+
+template <typename ValueType>
+Vector<ValueType> & Vector<ValueType>::operator+=(const ValueType & value) {
+ this->add(value);
+ return *this;
+}
+
+template <typename ValueType>
+bool Vector<ValueType>::operator==(const Vector & v2) {
+ if (this->size() != v2.size()) {
+ return false;
+ }
+ for (int i = 0, size = this->size(); i < size; i++) {
+ if (this->get(i) != v2.get(i)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename ValueType>
+bool Vector<ValueType>::operator!=(const Vector & v2) {
+ return !(*this == v2);
+}
+
+template <typename ValueType>
+std::string Vector<ValueType>::toString() {
+ ostringstream os;
+ os << *this;
+ return os.str();
+}
+
+/*
+ * Implementation notes: copy constructor and assignment operator
+ * --------------------------------------------------------------
+ * The constructor and assignment operators follow a standard paradigm,
+ * as described in the associated textbook.
+ */
+
+template <typename ValueType>
+Vector<ValueType>::Vector(const Vector & src) {
+ deepCopy(src);
+}
+
+template <typename ValueType>
+Vector<ValueType> & Vector<ValueType>::operator=(const Vector & src) {
+ if (this != &src) {
+ if (elements != NULL) delete[] elements;
+ deepCopy(src);
+ }
+ return *this;
+}
+
+template <typename ValueType>
+void Vector<ValueType>::deepCopy(const Vector & src) {
+ count = capacity = src.count;
+ elements = (capacity == 0) ? NULL : new ValueType[capacity];
+ for (int i = 0; i < count; i++) {
+ elements[i] = src.elements[i];
+ }
+}
+
+/*
+ * Implementation notes: The , operator
+ * ------------------------------------
+ * The comma operator works adding the right operand to the vector and
+ * then returning the vector by reference so that it is set for the next
+ * value in the chain.
+ */
+
+template <typename ValueType>
+Vector<ValueType> & Vector<ValueType>::operator,(const ValueType & value) {
+ this->add(value);
+ return *this;
+}
+
+/*
+ * Implementation notes: mapAll
+ * ----------------------------
+ * The various versions of the mapAll function apply the function or
+ * function object to each element in ascending index order.
+ */
+
+template <typename ValueType>
+void Vector<ValueType>::mapAll(void (*fn)(ValueType)) const {
+ for (int i = 0; i < count; i++) {
+ fn(elements[i]);
+ }
+}
+
+template <typename ValueType>
+void Vector<ValueType>::mapAll(void (*fn)(const ValueType &)) const {
+ for (int i = 0; i < count; i++) {
+ fn(elements[i]);
+ }
+}
+
+template <typename ValueType>
+template <typename FunctorType>
+void Vector<ValueType>::mapAll(FunctorType fn) const {
+ for (int i = 0; i < count; i++) {
+ fn(elements[i]);
+ }
+}
+
+/*
+ * Implementation notes: expandCapacity
+ * ------------------------------------
+ * This function doubles the array capacity, copies the old elements
+ * into the new array, and then frees the old one.
+ */
+
+template <typename ValueType>
+void Vector<ValueType>::expandCapacity() {
+ capacity = max(1, capacity * 2);
+ ValueType *array = new ValueType[capacity];
+ for (int i = 0; i < count; i++) {
+ array[i] = elements[i];
+ }
+ if (elements != NULL) delete[] elements;
+ elements = array;
+}
+
+/*
+ * Implementation notes: << and >>
+ * -------------------------------
+ * The insertion and extraction operators use the template facilities in
+ * strlib.h to read and write generic values in a way that treats strings
+ * specially.
+ */
+
+template <typename ValueType>
+std::ostream & operator<<(std::ostream & os, const Vector<ValueType> & vec) {
+ os << "{";
+ int len = vec.size();
+ for (int i = 0; i < len; i++) {
+ if (i > 0) os << ", ";
+ writeGenericValue(os, vec[i], true);
+ }
+ return os << "}";
+}
+
+template <typename ValueType>
+std::istream & operator>>(std::istream & is, Vector<ValueType> & vec) {
+ char ch;
+ is >> ch;
+ if (ch != '{') error("operator >>: Missing {");
+ vec.clear();
+ is >> ch;
+ if (ch != '}') {
+ is.unget();
+ while (true) {
+ ValueType value;
+ readGenericValue(is, value);
+ vec += value;
+ is >> ch;
+ if (ch == '}') break;
+ if (ch != ',') {
+ error(std::string("operator >>: Unexpected character ") + ch);
+ }
+ }
+ }
+ return is;
+}
+
+// hashing functions for vectors; defined in hashmap.cpp
+int hashCode(const Vector<std::string>& v);
+int hashCode(const Vector<int>& v);
+int hashCode(const Vector<char>& v);
+int hashCode(const Vector<long>& v);
+int hashCode(const Vector<double>& v);
+
+#endif
diff --git a/labb8/lib/readme.txt b/labb8/lib/readme.txt
new file mode 100755
index 0000000..9d0d5c8
--- /dev/null
+++ b/labb8/lib/readme.txt
@@ -0,0 +1,4 @@
+This directory contains any libraries that should be
+linked to your project when it is built.
+The most common library we will link to is the
+Stanford C++ library (cpplib).
diff --git a/labb8/lib/spl.jar b/labb8/lib/spl.jar
new file mode 100755
index 0000000..3cdc64f
--- /dev/null
+++ b/labb8/lib/spl.jar
Binary files differ