summaryrefslogtreecommitdiffstats
path: root/labb5/lib/StanfordCPPLib/foreach.h
diff options
context:
space:
mode:
Diffstat (limited to 'labb5/lib/StanfordCPPLib/foreach.h')
-rwxr-xr-xlabb5/lib/StanfordCPPLib/foreach.h217
1 files changed, 217 insertions, 0 deletions
diff --git a/labb5/lib/StanfordCPPLib/foreach.h b/labb5/lib/StanfordCPPLib/foreach.h
new file mode 100755
index 0000000..15a758b
--- /dev/null
+++ b/labb5/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