From fb80ac50825c7ca1fa063d3493175b7b27adbdb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Tue, 17 Nov 2020 15:42:27 +0100 Subject: add given code --- labb5/lib/StanfordCPPLib/foreach.h | 217 +++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100755 labb5/lib/StanfordCPPLib/foreach.h (limited to 'labb5/lib/StanfordCPPLib/foreach.h') 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 foreach keyword, which implements + * a substitute for the range-based for 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 + * foreach also supports C++ strings and arrays. + */ + +#ifndef _foreach_h +#define _foreach_h + +/* + * Statement: foreach + * Usage: foreach (type var in collection) { ... } + * ----------------------------------------------- + * The foreach 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. + * + *

The following code, for example, prints every element in the + * string vector lines: + * + *

+ *    foreach (string str in lines) {
+ *       cout << str << endl;
+ *    }
+ *
+ * + * Similarly, the following function calculates the sum of the character + * codes in a string: + * + *
+ *    int sumCharacterCodes(string str) {
+ *       int sum = 0;
+ *       foreach (char ch in str) sum += ch;
+ *       return sum;
+ *    }
+ *
+ * + * As a simplification when iterating over maps, the foreach + * 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 +#include +#include +#include + +/* These #includes are for files that contain "in" as a token */ + +#include +#include +#include +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 + struct ArrayRange : Range { + ArrayRange(const T *begin, const T *end) : iter(begin), end(end) { } + const T *iter; + const T *end; + }; + + template + struct CRange : Range { + CRange(const CType& c) : + cont(c), iter(cont.begin()), end(cont.end()) { } + CType cont; + typename CType::iterator iter, end; + }; + + template + struct MapRange : Range { + MapRange(const map & c) : + cont(c), iter(cont.begin()), end(cont.end()) { } + map cont; + typename map::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 + 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 + CRange *Init(State & fe, const CType & collection) { + fe.itr = new CRange(collection); + return (CRange*) fe.itr; + } + + template + typename iterator_traits::value_type + Hook(State & fe, CRange *) { + return HookImpl, + typename iterator_traits::value_type>(fe); + } + +/* For maps */ + + template + MapRange *Init(State & fe, const map & collection) { + fe.itr = new MapRange(collection); + return (MapRange*) fe.itr; + } + + template + 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 + K Hook(State & fe, MapRange *) { + return MapHookImpl,K>(fe); + } + +/* For C strings */ + + template + ArrayRange *Init(State & fe, char (&str)[n]) { + fe.itr = new ArrayRange(str, str + strlen(str)); + return (ArrayRange*) fe.itr; + } + + template + ArrayRange *Init(State & fe, const char (&str)[n]) { + fe.itr = new ArrayRange(str, str + strlen(str)); + return (ArrayRange*) fe.itr; + } + +/* For arrays */ + + template + ArrayRange *Init(State & fe, T (&arr)[n]) { + fe.itr = new ArrayRange(arr, arr + n); + return (ArrayRange*) fe.itr; + } + + template + ArrayRange *Init(State & fe, const T (&arr)[n]) { + fe.itr = new ArrayRange(arr, arr + n); + return (ArrayRange*) fe.itr; + } + + template + T Hook(State& fe, ArrayRange*) { + return HookImpl, 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 -- cgit v1.2.1