=== modified file 'src/libmatrix/Makefile'
@@ -21,7 +21,7 @@
program.o: program.cc program.h mat.h vec.h
log.o: log.cc log.h
util.o: util.cc util.h
-shader-source.o: shader-source.cc shader-source.h mat.h vec.h
+shader-source.o: shader-source.cc shader-source.h mat.h vec.h util.h
libmatrix.a : mat.o stack.h program.o log.o util.o shader-source.o
$(AR) -r $@ $(LIBOBJS)
=== modified file 'src/libmatrix/util.cc'
@@ -22,21 +22,58 @@
#include "log.h"
#include "util.h"
-/**
- * Splits a string using a delimiter
- *
- * @param s the string to split
- * @param delim the delimitir to use
- * @param elems the string vector to populate
- */
+using std::string;
+using std::vector;
+
void
-Util::split(const std::string &s, char delim, std::vector<std::string> &elems)
+Util::split(const string& src, char delim, vector<string>& elementVec, bool fuzzy)
{
- std::stringstream ss(s);
-
- std::string item;
- while(std::getline(ss, item, delim))
- elems.push_back(item);
+ // Trivial rejection
+ if (src.empty())
+ {
+ return;
+ }
+
+ // Simple case: we want to enforce the value of 'delim' strictly
+ if (!fuzzy)
+ {
+ std::stringstream ss(src);
+ string item;
+ while(std::getline(ss, item, delim))
+ elementVec.push_back(item);
+ return;
+ }
+
+ // Fuzzy case: Initialize our delimiter string based upon the caller's plus
+ // a space to allow for more flexibility.
+ string delimiter(" ");
+ delimiter += delim;
+ // Starting index into the string of the first token (by definition, if
+ // we're parsing a string, there is at least one token).
+ string::size_type startPos(0);
+ // string::find_first_of() looks for any character in the string provided,
+ // it is not treated as a sub-string, so regardless of where the space or
+ // comma is or how many there are, the result is the same.
+ string str(src);
+ string::size_type endPos = str.find_first_of(delimiter);
+ while (endPos != string::npos)
+ {
+ // Push back the current element starting at startPos for
+ // (endPos - startPos) characters. std::string takes care of
+ // terminators, etc.
+ elementVec.push_back(string(str, startPos, endPos - startPos));
+ // Index of the next element after any delimiter characters. Same
+ // caveat applies to find_first_not_of() that applies to
+ // find_first_of(); endPos tells it where to start the search.
+ string::size_type nextPos = str.find_first_not_of(delimiter, endPos);
+ // Erase the part of the string we've already parsed.
+ str = str.erase(startPos, nextPos - startPos);
+ // Look for the next delimiter. If there isn't one, we bail out.
+ endPos = str.find_first_of(delimiter);
+ }
+ // Regardless of whether we initially had one element or many, 'str' now
+ // only contains one.
+ elementVec.push_back(str);
}
uint64_t
=== modified file 'src/libmatrix/util.h'
@@ -24,10 +24,53 @@
#endif
struct Util {
- static void split(const std::string &s, char delim, std::vector<std::string> &elems);
+ /**
+ * split() - Splits a string into elements using a provided delimiter
+ *
+ * @s: the string to split
+ * @delim: the delimiter to use
+ * @elems: the string vector to populate
+ * @fuzzy: (optional) enable/disable strict handling of @delim
+ *
+ * Using @delim to determine field boundaries, splits @s into separate
+ * string elements. These elements are returned in the string vector
+ * @elems. If @fuzzy is true, then the handling of @delim allows for
+ * spaces and multiple consecutive occurences of @delim in determining
+ * field boundaries. As long as @s is non-empty, there will be at least
+ * one element in @elems.
+ */
+ static void split(const std::string &s, char delim, std::vector<std::string> &elems, bool fuzzy = false);
+ /**
+ * get_timestamp_us() - Returns the current time in microseconds
+ */
static uint64_t get_timestamp_us();
+ /**
+ * get_resource() - Gets an input filestream for a given file.
+ *
+ * @path: the path to the file
+ *
+ * Returns a pointer to an input stream, which must be deleted when no
+ * longer in use.
+ */
static std::istream *get_resource(const std::string &path);
+ /**
+ * list_files() - Get a list of the files in a given directory.
+ *
+ * @dirName: the directory path to be listed.
+ * @fileVec: the string vector to populate.
+ *
+ * Obtains a list of the files in @dirName, and returns them in the string
+ * vector @fileVec.
+ */
static void list_files(const std::string& dirName, std::vector<std::string>& fileVec);
+ /**
+ * dispose_pointer_vector() - cleans up a vector of pointers
+ *
+ * @vec: vector of pointers to objects or plain-old-data
+ *
+ * Iterates across @vec and deletes the data pointed to by each of the
+ * elements. Clears the vector, resetting it for reuse.
+ */
template <class T> static void dispose_pointer_vector(std::vector<T*> &vec)
{
for (typename std::vector<T*>::const_iterator iter = vec.begin();
@@ -39,16 +82,25 @@
vec.clear();
}
+ /**
+ * toString() - Converts a string to a plain-old-data type.
+ *
+ * @asString: a string representation of plain-old-data.
+ */
template<typename T>
static T
fromString(const std::string& asString)
{
std::stringstream ss(asString);
- T retVal;
+ T retVal = T();
ss >> retVal;
return retVal;
}
-
+ /**
+ * toString() - Converts a plain-old-data type to a string.
+ *
+ * @t: a simple value to be converted to a string
+ */
template<typename T>
static std::string
toString(const T t)
@@ -57,6 +109,13 @@
ss << t;
return ss.str();
}
+ /**
+ * appname_from_path() - get the name of an executable from an absolute path
+ *
+ * @path: absolute path of the running application (argv[0])
+ *
+ * Returns the last portion of @path (everything after the final '/').
+ */
static std::string
appname_from_path(const std::string& path);