diff --git a/Jupiter/Jupiter.vcxproj b/Jupiter/Jupiter.vcxproj
index adacc60..b81cc9d 100644
--- a/Jupiter/Jupiter.vcxproj
+++ b/Jupiter/Jupiter.vcxproj
@@ -132,6 +132,8 @@
+
+
diff --git a/Jupiter/Jupiter.vcxproj.filters b/Jupiter/Jupiter.vcxproj.filters
index 2ca4bfb..fe61b68 100644
--- a/Jupiter/Jupiter.vcxproj.filters
+++ b/Jupiter/Jupiter.vcxproj.filters
@@ -203,6 +203,12 @@
Header Files\Strings
+
+ Header Files\Strings
+
+
+ Header Files\Strings
+
diff --git a/Jupiter/Readable_String.h b/Jupiter/Readable_String.h
new file mode 100644
index 0000000..83c7485
--- /dev/null
+++ b/Jupiter/Readable_String.h
@@ -0,0 +1,181 @@
+/**
+ * Copyright (C) 2014 Justin James.
+ *
+ * This license must be preserved.
+ * Any applications, libraries, or code which make any use of any
+ * component of this program must not be commercial, unless explicit
+ * permission is granted from the original author. The use of this
+ * program for non-profit purposes is permitted.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * In the event that this license restricts you from making desired use of this program, contact the original author.
+ * Written by Justin James
+ */
+
+#if !defined _READABLE_STRING_H_HEADER
+#define _READABLE_STRING_H_HEADER
+
+/**
+ * @file Readable_String.h
+ * @brief Defines several basic accessive and comparative virtual functions for strings.
+ */
+
+#include // wchar_t
+#include // FILE
+#include // std::basic_string type
+
+namespace Jupiter
+{
+
+ /**
+ * @brief Provides the basis for String classes by providing implementations for operators, comparative operations, and defining abstract functions.
+ * Note: This is an abstract type.
+ *
+ * @param T Element type which the String will store. Defaults to char.
+ */
+ template class Readable_String
+ {
+ public:
+
+ /**
+ * @brief Fetches an element from the string.
+ *
+ * @param index Index of the element to return.
+ * @return The element located at the specified index.
+ */
+ virtual T &get(size_t index) const = 0;
+
+ /**
+ * @brief Returns the number of elements in the String.
+ *
+ * @return Number of elements in the string.
+ */
+ virtual size_t size() const = 0;
+
+ /**
+ * @brief Returns a pointer to the underlying string of elements.
+ *
+ * @return Pointer to the underlying string of elements.
+ */
+ virtual const T *ptr() const = 0;
+
+ /**
+ * @brief Checks if the string contains an element with the specified value.
+ *
+ * @param value Value of the element to search for.
+ * @return True if a match is found, false otherwise.
+ */
+ bool contains(const T &value) const;
+
+ /**
+ * @brief Compares another string against the String.
+ *
+ * @param in String to compare against.
+ * @return 0 if the strings are equal, negative if the first mismatched character is greater in the String, or positive if it's less.
+ */
+ int compare(const Readable_String &in) const;
+ int compare(const std::basic_string &in) const;
+ int compare(const T *in) const;
+ int compare(const T &in) const;
+ int compare(const std::nullptr_t) const;
+
+ /**
+ * @brief Checks if the strings are equal.
+ * Note: Case sensitive.
+ *
+ * @param in String to compare against.
+ * @return True if the contents of the strings are equal, false otherwise.
+ */
+ bool equals(const Readable_String &in) const;
+ bool equals(const std::basic_string &in) const;
+ bool equals(const T *in) const;
+ bool equals(const T &in) const;
+ bool equals(const std::nullptr_t) const;
+
+ /**
+ * @brief Checks if the strings are equal.
+ * Note: Case insensitive. Returns false for any type other than char and wchar_t.
+ *
+ * @param in String to compare against.
+ * @return True if the contents of the strings are equal, false otherwise.
+ */
+ bool equalsi(const Readable_String &in) const;
+ bool equalsi(const std::basic_string &in) const;
+ bool equalsi(const T *in) const;
+ bool equalsi(const T &in) const;
+ bool equalsi(const std::nullptr_t) const;
+
+ /**
+ * @brief Checks if the String matches a wildcard format.
+ * Note: Case sensitive.
+ *
+ * @param format Format that the string is compared against.
+ * @return True if the String matches the wildcard format, false otherwise.
+ */
+ bool match(const Readable_String &format) const;
+ bool match(const std::basic_string &format) const;
+ bool match(const T *format) const;
+
+ /**
+ * @brief Checks if the CString matches a wildcard format.
+ * Note: Case insensitive. Returns false for any type other than char and wchar_t.
+ *
+ * @param format Format that the string is compared against.
+ * @return True if the CString matches the wildcard format, false otherwise.
+ */
+ bool matchi(const Readable_String &format) const;
+ bool matchi(const std::basic_string &format) const;
+ bool matchi(const T *format) const;
+
+ /**
+ * @brief Counts the number of token deliminated words.
+ *
+ * @param whitespace A string of tokens used to deliminate words.
+ * @return Number of words found.
+ */
+ unsigned int wordCount(const T *whitespace) const;
+
+ /**
+ * @brief Interprets the string as an integer.
+ * Note: This returns 0 on any value string type other than char.
+ *
+ * @param base Base of the string representation.
+ * @return Integer representation of the string.
+ */
+ int asInt(int base = 0) const;
+
+ /**
+ * @brief Interprets the string as an integer.
+ * Note: This returns 0 on any value string type other than char.
+ *
+ * @param base Base of the string representation.
+ * @return Integer representation of the string.
+ */
+ unsigned int asUnsignedInt(int base = 0) const;
+
+ /**
+ * @brief Outputs the string to a FILE stream.
+ *
+ * @param out Stream to output to.
+ * @return Number of elements written successfully.
+ */
+ size_t print(FILE *out) const;
+ size_t print(std::basic_ostream &out) const;
+
+ /**
+ * @brief Outputs the string and a newline to a FILE stream
+ *
+ * @param out Stream to output to.
+ * @param Number of elements written successfully.
+ */
+ size_t println(FILE *out) const;
+ size_t println(std::basic_ostream &out) const;
+ };
+}
+
+#include "Readable_String_Imp.h"
+
+#endif // _READABLE_STRING_H_HEADER
\ No newline at end of file
diff --git a/Jupiter/Readable_String_Imp.h b/Jupiter/Readable_String_Imp.h
new file mode 100644
index 0000000..e624e1a
--- /dev/null
+++ b/Jupiter/Readable_String_Imp.h
@@ -0,0 +1,746 @@
+/**
+ * Copyright (C) 2014 Justin James.
+ *
+ * This license must be preserved.
+ * Any applications, libraries, or code which make any use of any
+ * component of this program must not be commercial, unless explicit
+ * permission is granted from the original author. The use of this
+ * program for non-profit purposes is permitted.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * In the event that this license restricts you from making desired use of this program, contact the original author.
+ * Written by Justin James
+ */
+
+#if !defined _READABLE_STRING_IMP_H_HEADER
+#define _READABLE_STRING_IMP_H_HEADER
+
+/**
+ * @file Readable_String_Imp.h
+ * @brief Provides the implementations for Readable_String functions.
+ * Note: Modification of this file is not supported in any way.
+ */
+
+#include "Readable_String.h"
+#include "Functions.h"
+
+/**
+* IMPLEMENTATION:
+* Readable_String
+*/
+
+// contains
+
+template bool Jupiter::Readable_String::contains(const T &value) const
+{
+ for (size_t i = 0; i != this->size(); i++) if (this->get(i) == value) return true;
+ return false;
+}
+
+// compare()
+
+template int Jupiter::Readable_String::compare(const Jupiter::Readable_String &in) const
+{
+ // rewrite to compare multiple bytes at a time.
+ size_t index = 0;
+ while (this->get(index) == in.get(index))
+ {
+ index++;
+ if (index == in.size())
+ {
+ if (index == this->size()) return 0;
+ return 1;
+ }
+ if (index == this->size()) return 0 - in.get(index);
+ }
+ return this->get(index) - in.get(index);
+}
+
+template int Jupiter::Readable_String::compare(const std::basic_string &in) const
+{
+ // rewrite to compare multiple bytes at a time.
+ size_t index = 0;
+ while (this->get(index) == in.at(index))
+ {
+ index++;
+ if (index == in.size())
+ {
+ if (index == this->size()) return 0;
+ return 1;
+ }
+ if (index == this->size()) return 0 - in.at(index);
+ }
+ return this->get(index) - in.at(index);
+}
+
+template int Jupiter::Readable_String::compare(const T *s2) const
+{
+ if (this->size() == 0) return 0 - *s2;
+ size_t index = 0;
+ while (this->get(index) == *s2)
+ {
+ index++;
+ if (*s2 == 0)
+ {
+ if (index == this->size()) return 0;
+ return 1;
+ }
+ s2++;
+ if (index == this->size()) return 0 - *s2;
+ }
+ return this->get(index) - *s2;
+}
+
+template int Jupiter::Readable_String::compare(const T &in) const
+{
+ if (this->size() == 0) return 0 - in;
+ return this->get(0) - in;
+}
+
+template int Jupiter::Readable_String::compare(const std::nullptr_t) const
+{
+ if (this->size() == 0) return true;
+ return this->get(0);
+}
+
+// equals()
+
+template bool Jupiter::Readable_String::equals(const Jupiter::Readable_String &in) const
+{
+ if (this->size() != in.size()) return false;
+
+ // rewrite to compare multiple bytes at a time.
+ size_t index = 0;
+ while (index != this->size())
+ {
+ if (this->get(index) != in.get(index)) return false;
+ index++;
+ }
+ return true;
+}
+
+template bool Jupiter::Readable_String::equals(const std::basic_string &in) const
+{
+ if (this->size() != in.size()) return false;
+ // rewrite to compare multiple bytes at a time.
+ size_t index = 0;
+ while (index != this->size())
+ {
+ if (this->get(index) != in.at(index)) return false;
+ index++;
+ }
+ return true;
+}
+
+template bool Jupiter::Readable_String::equals(const T *in) const
+{
+ if (in == nullptr) return this->size() == 0;
+ for (size_t index = 0; index != this->size(); index++)
+ {
+ if (*in == 0 || this->get(index) != *in) return false;
+ in++;
+ }
+ return *in == 0;
+}
+
+template bool Jupiter::Readable_String::equals(const T &in) const
+{
+ return this->size() == 1 && this->get(0) == in;
+}
+
+template bool Jupiter::Readable_String::equals(std::nullptr_t) const
+{
+ return this->size() == 0;
+}
+
+// equalsi()
+
+template<> bool inline Jupiter::Readable_String::equalsi(const Jupiter::Readable_String &in) const
+{
+ if (this->size() != in.size()) return false;
+ for (size_t index = 0; index != this->size(); index++)
+ {
+ if (toupper(this->get(index)) != toupper(in.get(index))) return false;
+ }
+ return true;
+}
+
+template<> bool inline Jupiter::Readable_String::equalsi(const Jupiter::Readable_String &in) const
+{
+ if (this->size() != in.size()) return false;
+ for (size_t index = 0; index != this->size(); index++)
+ {
+ if (towupper(this->get(index)) != towupper(in.get(index))) return false;
+ }
+ return true;
+}
+
+template bool Jupiter::Readable_String::equalsi(const Jupiter::Readable_String &in) const
+{
+ return this->equals(in); // Concept of "case" not supported for type.
+}
+
+template<> bool inline Jupiter::Readable_String::equalsi(const std::basic_string &in) const
+{
+ if (this->size() != in.size()) return false;
+ for (size_t index = 0; index != this->size(); index++)
+ {
+ if (toupper(this->get(index)) != toupper(in.at(index))) return false;
+ }
+ return true;
+}
+
+template<> bool inline Jupiter::Readable_String::equalsi(const std::basic_string &in) const
+{
+ if (this->size() != in.size()) return false;
+ for (size_t index = 0; index != this->size(); index++)
+ {
+ if (towupper(this->get(index)) != towupper(in.at(index))) return false;
+ }
+ return true;
+}
+
+template bool Jupiter::Readable_String::equalsi(const std::basic_string &in) const
+{
+ return this->equals(in); // Concept of "case" not supported for type.
+}
+
+template<> bool inline Jupiter::Readable_String::equalsi(const char *in) const
+{
+ if (in == nullptr) return this->size() == 0;
+ for (size_t index = 0; index != this->size(); index++)
+ {
+ if (*in == 0 || toupper(this->get(index)) != toupper(*in)) return false;
+ in++;
+ }
+ return *in == 0;
+}
+
+template<> bool inline Jupiter::Readable_String::equalsi(const wchar_t *in) const
+{
+ if (in == nullptr) return this->size() == 0;
+ for (size_t index = 0; index != this->size(); index++)
+ {
+ if (*in == 0 || towupper(this->get(index)) != towupper(*in)) return false;
+ in++;
+ }
+ return *in == 0;
+}
+
+template bool Jupiter::Readable_String::equalsi(const T *in) const
+{
+ return this->equals(in); // Concept of "case" not supported for type.
+}
+
+template<> bool inline Jupiter::Readable_String::equalsi(const char &in) const
+{
+ return this->size() == 1 && toupper(this->get(0)) == toupper(in);
+}
+
+template<> bool inline Jupiter::Readable_String::equalsi(const wchar_t &in) const
+{
+ return this->size() == 1 && towupper(this->get(0)) == towupper(in);
+}
+
+template bool Jupiter::Readable_String::equalsi(const T &in) const
+{
+ return this->equals(in); // Concept of "case" not supported for type.
+}
+
+template bool Jupiter::Readable_String::equalsi(const std::nullptr_t) const
+{
+ return this->size() == 0;
+}
+
+// match()
+
+template<> bool inline Jupiter::Readable_String::match(const Jupiter::Readable_String &format) const
+{
+ size_t index = 0;
+ size_t formatIndex = 0;
+ while (formatIndex != format.size())
+ {
+ if (format.get(formatIndex) == '*')
+ {
+ formatIndex++;
+ while (format.get(formatIndex) == '?')
+ {
+ if (this->get(index) == 0) return false;
+ formatIndex++;
+ index++;
+ }
+ if (format.get(formatIndex) == 0) return true;
+ if (format.get(formatIndex) == '*') continue;
+ while (format.get(formatIndex) != this->get(index))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (format.get(formatIndex) != '?' && format.get(formatIndex) != this->get(index)) return false;
+ formatIndex++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template<> bool inline Jupiter::Readable_String::match(const Jupiter::Readable_String &format) const
+{
+ size_t index = 0;
+ size_t formatIndex = 0;
+ while (formatIndex != format.size())
+ {
+ if (format.get(formatIndex) == '*')
+ {
+ formatIndex++;
+ while (format.get(formatIndex) == '?')
+ {
+ if (this->get(index) == 0) return false;
+ formatIndex++;
+ index++;
+ }
+ if (format.get(formatIndex) == 0) return true;
+ if (format.get(formatIndex) == '*') continue;
+ while (format.get(formatIndex) != this->get(index))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (format.get(formatIndex) != '?' && format.get(formatIndex) != this->get(index)) return false;
+ formatIndex++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template bool Jupiter::Readable_String::match(const Jupiter::Readable_String &format) const
+{
+ return false; // Wildcard matching not supported for type.
+}
+
+template<> bool inline Jupiter::Readable_String::match(const std::basic_string &format) const
+{
+ size_t index = 0;
+ size_t formatIndex = 0;
+ while (formatIndex != format.size())
+ {
+ if (format.at(formatIndex) == '*')
+ {
+ formatIndex++;
+ while (format.at(formatIndex) == '?')
+ {
+ if (this->get(index) == 0) return false;
+ formatIndex++;
+ index++;
+ }
+ if (format.at(formatIndex) == 0) return true;
+ if (format.at(formatIndex) == '*') continue;
+ while (format.at(formatIndex) != this->get(index))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (format.at(formatIndex) != '?' && format.at(formatIndex) != this->get(index)) return false;
+ formatIndex++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template<> bool inline Jupiter::Readable_String::match(const std::basic_string &format) const
+{
+ size_t index = 0;
+ size_t formatIndex = 0;
+ while (formatIndex != format.size())
+ {
+ if (format.at(formatIndex) == '*')
+ {
+ formatIndex++;
+ while (format.at(formatIndex) == '?')
+ {
+ if (this->get(index) == 0) return false;
+ formatIndex++;
+ index++;
+ }
+ if (format.at(formatIndex) == 0) return true;
+ if (format.at(formatIndex) == '*') continue;
+ while (format.at(formatIndex) != this->get(index))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (format.at(formatIndex) != '?' && format.at(formatIndex) != this->get(index)) return false;
+ formatIndex++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template bool Jupiter::Readable_String::match(const std::basic_string &format) const
+{
+ return false; // Wildcard matching not supported for type.
+}
+
+template<> inline bool Jupiter::Readable_String::match(const char *format) const
+{
+ size_t index = 0;
+ while (*format != 0)
+ {
+ if (*format == '*')
+ {
+ format++;
+ while (*format == '?')
+ {
+ if (this->get(index) == 0) return false;
+ format++;
+ index++;
+ }
+ if (*format == 0) return true;
+ if (*format == '*') continue;
+ while (*format != this->get(index))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (*format != '?' && *format != this->get(index)) return false;
+ format++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template<> inline bool Jupiter::Readable_String::match(const wchar_t *format) const
+{
+ size_t index = 0;
+ while (*format != 0)
+ {
+ if (*format == L'*')
+ {
+ format++;
+ while (*format == L'?')
+ {
+ if (this->get(index) == 0) return false;
+ format++;
+ index++;
+ }
+ if (*format == 0) return true;
+ if (*format == L'*') continue;
+ while (*format != this->get(index))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (*format != L'?' && *format != this->get(index)) return false;
+ format++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template bool Jupiter::Readable_String::match(const T *format) const
+{
+ return false; // Wildcard matching not supported for type.
+}
+
+// matchi()
+
+template<> bool inline Jupiter::Readable_String::matchi(const Jupiter::Readable_String &format) const
+{
+ int fUpper;
+ size_t index = 0;
+ size_t formatIndex = 0;
+ while (formatIndex != format.size())
+ {
+ if (format.get(formatIndex) == L'*')
+ {
+ formatIndex++;
+ while (format.get(formatIndex) == L'?')
+ {
+ if (this->get(index) == 0) return false;
+ formatIndex++;
+ index++;
+ }
+ if (format.get(formatIndex) == 0) return true;
+ if (format.get(formatIndex) == '*') continue;
+ fUpper = toupper(format.get(formatIndex));
+ while (fUpper != toupper(this->get(index)))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (format.get(formatIndex) != L'?' && toupper(format.get(formatIndex)) != toupper(this->get(index))) return false;
+ formatIndex++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template<> bool inline Jupiter::Readable_String::matchi(const Jupiter::Readable_String &format) const
+{
+ wint_t fUpper;
+ size_t index = 0;
+ size_t formatIndex = 0;
+ while (formatIndex != format.size())
+ {
+ if (format.get(formatIndex) == L'*')
+ {
+ formatIndex++;
+ while (format.get(formatIndex) == L'?')
+ {
+ if (this->get(index) == 0) return false;
+ formatIndex++;
+ index++;
+ }
+ if (format.get(formatIndex) == 0) return true;
+ if (format.get(formatIndex) == '*') continue;
+ fUpper = towupper(format.get(formatIndex));
+ while (fUpper != towupper(this->get(index)))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (format.get(formatIndex) != L'?' && towupper(format.get(formatIndex)) != towupper(this->get(index))) return false;
+ formatIndex++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template bool Jupiter::Readable_String::matchi(const Jupiter::Readable_String &format) const
+{
+ return false; // Wildcard matching not supported for type. Concept of "case" not supported for type.
+}
+
+template<> bool inline Jupiter::Readable_String::matchi(const std::basic_string &format) const
+{
+ int fUpper;
+ size_t index = 0;
+ size_t formatIndex = 0;
+ while (formatIndex != format.size())
+ {
+ if (format.at(formatIndex) == L'*')
+ {
+ formatIndex++;
+ while (format.at(formatIndex) == L'?')
+ {
+ if (this->get(index) == 0) return false;
+ formatIndex++;
+ index++;
+ }
+ if (format.at(formatIndex) == 0) return true;
+ if (format.at(formatIndex) == '*') continue;
+ fUpper = toupper(format.at(formatIndex));
+ while (fUpper != toupper(this->get(index)))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (format.at(formatIndex) != L'?' && toupper(format.at(formatIndex)) != toupper(this->get(index))) return false;
+ formatIndex++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template<> bool inline Jupiter::Readable_String::matchi(const std::basic_string &format) const
+{
+ wint_t fUpper;
+ size_t index = 0;
+ size_t formatIndex = 0;
+ while (formatIndex != format.size())
+ {
+ if (format.at(formatIndex) == L'*')
+ {
+ formatIndex++;
+ while (format.at(formatIndex) == L'?')
+ {
+ if (this->get(index) == 0) return false;
+ formatIndex++;
+ index++;
+ }
+ if (format.at(formatIndex) == 0) return true;
+ if (format.at(formatIndex) == '*') continue;
+ fUpper = towupper(format.at(formatIndex));
+ while (fUpper != towupper(this->get(index)))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (format.at(formatIndex) != L'?' && towupper(format.at(formatIndex)) != towupper(this->get(index))) return false;
+ formatIndex++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template bool Jupiter::Readable_String::matchi(const std::basic_string &format) const
+{
+ return false; // Wildcard matching not supported for type. Concept of "case" not supported for type.
+}
+
+template<> bool inline Jupiter::Readable_String::matchi(const char *format) const
+{
+ int fUpper;
+ size_t index = 0;
+ while (*format != 0)
+ {
+ if (*format == '*')
+ {
+ format++;
+ while (*format == '?')
+ {
+ if (this->get(index) == 0) return false;
+ format++;
+ index++;
+ }
+ if (*format == 0) return true;
+ if (*format == '*') continue;
+ fUpper = toupper(*format);
+ while (fUpper != toupper(this->get(index)))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (*format != '?' && toupper(*format) != toupper(this->get(index))) return false;
+ format++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template<> bool inline Jupiter::Readable_String::matchi(const wchar_t *format) const
+{
+ wint_t fUpper;
+ size_t index = 0;
+ while (*format != 0)
+ {
+ if (*format == L'*')
+ {
+ format++;
+ while (*format == L'?')
+ {
+ if (this->get(index) == 0) return false;
+ format++;
+ index++;
+ }
+ if (*format == 0) return true;
+ if (*format == '*') continue;
+ fUpper = towupper(*format);
+ while (fUpper != towupper(this->get(index)))
+ {
+ if (this->get(index) == 0) return false;
+ index++;
+ }
+ }
+ else if (*format != L'?' && towupper(*format) != towupper(this->get(index))) return false;
+ format++;
+ index++;
+ }
+ return index == this->size();
+}
+
+template bool Jupiter::Readable_String::matchi(const T *format) const
+{
+ return false; // Wildcard matching not supported for type. Concept of "case" not supported for type.
+}
+
+// wordCount()
+
+template unsigned int Jupiter::Readable_String::wordCount(const T *whitespace) const
+{
+ unsigned int result = 0;
+ const T *p = this->ptr();
+ bool prev = true;
+ while (*p != 0)
+ {
+ if (Jupiter::strpbrk(whitespace, *p) == nullptr) // This isn't whitespace!
+ {
+ if (prev == true) // We just left whitespace!
+ {
+ prev = false;
+ result++;
+ }
+ }
+ else prev = true; // This is whitespace!
+ p++;
+ }
+ return result;
+}
+
+// as
+
+template<> unsigned int inline Jupiter::Readable_String::asUnsignedInt(int base) const
+{
+ return strtoui_s(this->ptr(), this->size(), base);
+}
+
+template unsigned int Jupiter::Readable_String::asUnsignedInt(int base) const
+{
+ return 0;
+}
+
+template<> int inline Jupiter::Readable_String::asInt(int base) const
+{
+ return strtoi_s(this->ptr(), this->size(), base);
+}
+
+template int Jupiter::Readable_String::asInt(int base) const
+{
+ return 0;
+}
+
+// Stream output
+
+template size_t Jupiter::Readable_String::print(FILE *out) const
+{
+ return fwrite(this->ptr(), sizeof(T), this->size(), out);
+}
+
+template<> size_t inline Jupiter::Readable_String::print(FILE *out) const
+{
+ size_t index = 0;
+ while (index != this->size() && fputwc(this->get(index), out) != WEOF) index++;
+ return index;
+}
+
+template size_t Jupiter::Readable_String::print(std::basic_ostream &out) const
+{
+ size_t index = 0;
+ while (index != this->size())
+ {
+ out << this->get(index);
+ index++;
+ }
+ return index;
+}
+
+template size_t Jupiter::Readable_String::println(FILE *out) const
+{
+ size_t r = this->print(out);
+ if (r != this->size()) return r;
+ if (fputs("\r\n", out) != EOF) r += 2;
+ return r;
+}
+
+template size_t Jupiter::Readable_String::println(std::basic_ostream &out) const
+{
+ size_t r = this->print(out);
+ if (r != this->size()) return r;
+ out << std::endl;
+ return r;
+}
+
+#endif // _READABLE_STRING_IMP_H_HEADER
\ No newline at end of file
diff --git a/Jupiter/String_Type.h b/Jupiter/String_Type.h
index 358ee13..7e6e84e 100644
--- a/Jupiter/String_Type.h
+++ b/Jupiter/String_Type.h
@@ -24,11 +24,8 @@
* Note: Some methods are commented out. This means that they should be implemented, but could not be put declared in this template (return of abstract type).
*/
-#include "Jupiter.h"
-#include // std::basic_string type
#include // va_list
-#include
-#include
+#include "Readable_String.h"
namespace Jupiter
{
@@ -39,7 +36,7 @@ namespace Jupiter
*
* @param T Element type which the String will store. Defaults to char.
*/
- template class String_Type
+ template class String_Type : public Jupiter::Readable_String
{
public:
@@ -65,100 +62,6 @@ namespace Jupiter
*/
const T *ptr() const;
- /**
- * @brief Checks if the string contains an element with the specified value.
- *
- * @param value Value of the element to search for.
- * @return True if a match is found, false otherwise.
- */
- bool contains(const T &value) const;
-
- /**
- * @brief Compares another string against the String.
- *
- * @param in String to compare against.
- * @return 0 if the strings are equal, negative if the first mismatched character is greater in the String, or positive if it's less.
- */
- int compare(const String_Type &in) const;
- int compare(const std::basic_string &in) const;
- int compare(const T *in) const;
- int compare(const T &in) const;
- int compare(const std::nullptr_t) const;
-
- /**
- * @brief Checks if the strings are equal.
- * Note: Case sensitive.
- *
- * @param in String to compare against.
- * @return True if the contents of the strings are equal, false otherwise.
- */
- bool equals(const String_Type &in) const;
- bool equals(const std::basic_string &in) const;
- bool equals(const T *in) const;
- bool equals(const T &in) const;
- bool equals(const std::nullptr_t) const;
-
- /**
- * @brief Checks if the strings are equal.
- * Note: Case insensitive. Returns false for any type other than char and wchar_t.
- *
- * @param in String to compare against.
- * @return True if the contents of the strings are equal, false otherwise.
- */
- bool equalsi(const String_Type &in) const;
- bool equalsi(const std::basic_string &in) const;
- bool equalsi(const T *in) const;
- bool equalsi(const T &in) const;
- bool equalsi(const std::nullptr_t) const;
-
- /**
- * @brief Checks if the String matches a wildcard format.
- * Note: Case sensitive.
- *
- * @param format Format that the string is compared against.
- * @return True if the String matches the wildcard format, false otherwise.
- */
- bool match(const String_Type &format) const;
- bool match(const std::basic_string &format) const;
- bool match(const T *format) const;
-
- /**
- * @brief Checks if the CString matches a wildcard format.
- * Note: Case insensitive. Returns false for any type other than char and wchar_t.
- *
- * @param format Format that the string is compared against.
- * @return True if the CString matches the wildcard format, false otherwise.
- */
- bool matchi(const String_Type &format) const;
- bool matchi(const std::basic_string &format) const;
- bool matchi(const T *format) const;
-
- /**
- * @brief Counts the number of token deliminated words.
- *
- * @param whitespace A string of tokens used to deliminate words.
- * @return Number of words found.
- */
- unsigned int wordCount(const T *whitespace) const;
-
- /**
- * @brief Interprets the string as an integer.
- * Note: This returns 0 on any value string type other than char.
- *
- * @param base Base of the string representation.
- * @return Integer representation of the string.
- */
- int asInt(int base = 0) const;
-
- /**
- * @brief Interprets the string as an integer.
- * Note: This returns 0 on any value string type other than char.
- *
- * @param base Base of the string representation.
- * @return Integer representation of the string.
- */
- unsigned int asUnsignedInt(int base = 0) const;
-
/**
* @brief Returns a C-Style string version of the String.
*
@@ -166,24 +69,6 @@ namespace Jupiter
*/
virtual const T *c_str() const = 0;
- /**
- * @brief Outputs the string to a FILE stream.
- *
- * @param out Stream to output to.
- * @return Number of elements written successfully.
- */
- size_t print(FILE *out) const;
- size_t print(std::basic_ostream &out) const;
-
- /**
- * @brief Outputs the string and a newline to a FILE stream
- *
- * @param out Stream to output to.
- * @param Number of elements written successfully.
- */
- size_t println(FILE *out) const;
- size_t println(std::basic_ostream &out) const;
-
/**
* @brief Sets the CString's contents based on the format string and input variables.
* Note: Format specifiers similar to printf. Returns 0 for any type other than char and wchar_t.
diff --git a/Jupiter/String_Type_Imp.h b/Jupiter/String_Type_Imp.h
index e1d91f5..439ebd1 100644
--- a/Jupiter/String_Type_Imp.h
+++ b/Jupiter/String_Type_Imp.h
@@ -55,715 +55,6 @@ template const T *Jupiter::String_Type::ptr() const
return Jupiter::String_Type::str;
}
-template bool Jupiter::String_Type::contains(const T &value) const
-{
- for (unsigned int i = 0; i < Jupiter::String_Type::length; i++) if (Jupiter::String_Type::str[i] == value) return true;
- return false;
-}
-
-// compare()
-
-template int Jupiter::String_Type::compare(const Jupiter::String_Type &in) const
-{
- // rewrite to compare multiple bytes at a time.
- size_t index = 0;
- while (Jupiter::String_Type::str[index] == in.get(index))
- {
- index++;
- if (index == in.size())
- {
- if (index == Jupiter::String_Type::length) return 0;
- return 1;
- }
- if (index == Jupiter::String_Type::length) return 0 - in.get(index);
- }
- return Jupiter::String_Type::str[index] - in.get(index);
-}
-
-template int Jupiter::String_Type::compare(const std::basic_string &in) const
-{
- // rewrite to compare multiple bytes at a time.
- size_t index = 0;
- while (Jupiter::String_Type::str[index] == in.at(index))
- {
- index++;
- if (index == in.size())
- {
- if (index == Jupiter::String_Type::length) return 0;
- return 1;
- }
- if (index == Jupiter::String_Type::length) return 0 - in.at(index);
- }
- return Jupiter::String_Type::str[index] - in.at(index);
-}
-
-template int Jupiter::String_Type::compare(const T *s2) const
-{
- if (Jupiter::String_Type::length == 0) return 0 - *s2;
- size_t index = 0;
- while (Jupiter::String_Type::str[index] == *s2)
- {
- index++;
- if (*s2 == 0)
- {
- if (index == Jupiter::String_Type::length) return 0;
- return 1;
- }
- s2++;
- if (index == Jupiter::String_Type::length) return 0 - *s2;
- }
- return Jupiter::String_Type::str[index] - *s2;
-}
-
-template int Jupiter::String_Type::compare(const T &in) const
-{
- if (Jupiter::String_Type::length == 0) return 0 - in;
- return *Jupiter::String_Type::str - in;
-}
-
-template int Jupiter::String_Type::compare(const std::nullptr_t) const
-{
- if (Jupiter::String_Type::length == 0) return true;
- return *Jupiter::String_Type::str;
-}
-
-// equals()
-
-template bool Jupiter::String_Type::equals(const Jupiter::String_Type &in) const
-{
- if (Jupiter::String_Type::length != in.size()) return false;
-
- // rewrite to compare multiple bytes at a time.
- size_t index = 0;
- while (index != Jupiter::String_Type::length)
- {
- if (Jupiter::String_Type::str[index] != in.str[index]) return false;
- index++;
- }
- return true;
-}
-
-template bool Jupiter::String_Type::equals(const std::basic_string &in) const
-{
- if (Jupiter::String_Type::length != in.size()) return false;
- // rewrite to compare multiple bytes at a time.
- size_t index = 0;
- while (index != Jupiter::String_Type::length)
- {
- if (Jupiter::String_Type::str[index] != in.at(index)) return false;
- index++;
- }
- return true;
-}
-
-template bool Jupiter::String_Type::equals(const T *in) const
-{
- if (in == nullptr) return Jupiter::String_Type::length == 0;
- for (size_t index = 0; index != Jupiter::String_Type::length; index++)
- {
- if (*in == 0 || Jupiter::String_Type::str[index] != *in) return false;
- in++;
- }
- return *in == 0;
-}
-
-template bool Jupiter::String_Type::equals(const T &in) const
-{
- return Jupiter::String_Type::length == 1 && *Jupiter::String_Type::str == in;
-}
-
-template bool Jupiter::String_Type::equals(std::nullptr_t) const
-{
- return Jupiter::String_Type::length == 0;
-}
-
-// equalsi()
-
-template<> bool inline Jupiter::String_Type::equalsi(const Jupiter::String_Type &in) const
-{
- if (Jupiter::String_Type::length != in.size()) return false;
- for (size_t index = 0; index != Jupiter::String_Type::length; index++)
- {
- if (toupper(Jupiter::String_Type::str[index]) != toupper(in.str[index])) return false;
- }
- return true;
-}
-
-template<> bool inline Jupiter::String_Type::equalsi(const Jupiter::String_Type &in) const
-{
- if (Jupiter::String_Type::length != in.size()) return false;
- for (size_t index = 0; index != Jupiter::String_Type::length; index++)
- {
- if (towupper(Jupiter::String_Type::str[index]) != towupper(in.str[index])) return false;
- }
- return true;
-}
-
-template bool Jupiter::String_Type::equalsi(const Jupiter::String_Type &in) const
-{
- return Jupiter::String_Type::equals(in); // Concept of "case" not supported for type.
-}
-
-template<> bool inline Jupiter::String_Type::equalsi(const std::basic_string &in) const
-{
- if (Jupiter::String_Type::length != in.size()) return false;
- for (size_t index = 0; index != Jupiter::String_Type::length; index++)
- {
- if (toupper(Jupiter::String_Type::str[index]) != toupper(in.at(index))) return false;
- }
- return true;
-}
-
-template<> bool inline Jupiter::String_Type::equalsi(const std::basic_string &in) const
-{
- if (Jupiter::String_Type::length != in.size()) return false;
- for (size_t index = 0; index != Jupiter::String_Type::length; index++)
- {
- if (towupper(Jupiter::String_Type::str[index]) != towupper(in.at(index))) return false;
- }
- return true;
-}
-
-template bool Jupiter::String_Type::equalsi(const std::basic_string &in) const
-{
- return Jupiter::String_Type::equals(in); // Concept of "case" not supported for type.
-}
-
-template<> bool inline Jupiter::String_Type::equalsi(const char *in) const
-{
- if (in == nullptr) return Jupiter::String_Type::length == 0;
- for (size_t index = 0; index != Jupiter::String_Type::length; index++)
- {
- if (*in == 0 || toupper(Jupiter::String_Type::str[index]) != toupper(*in)) return false;
- in++;
- }
- return *in == 0;
-}
-
-template<> bool inline Jupiter::String_Type::equalsi(const wchar_t *in) const
-{
- if (in == nullptr) return Jupiter::String_Type::length == 0;
- for (size_t index = 0; index != Jupiter::String_Type::length; index++)
- {
- if (*in == 0 || towupper(Jupiter::String_Type::str[index]) != towupper(*in)) return false;
- in++;
- }
- return *in == 0;
-}
-
-template bool Jupiter::String_Type::equalsi(const T *in) const
-{
- return Jupiter::String_Type::equals(in); // Concept of "case" not supported for type.
-}
-
-template<> bool inline Jupiter::String_Type::equalsi(const char &in) const
-{
- return Jupiter::String_Type::length == 1 && toupper(*Jupiter::String_Type::str) == toupper(in);
-}
-
-template<> bool inline Jupiter::String_Type::equalsi(const wchar_t &in) const
-{
- return Jupiter::String_Type::length == 1 && towupper(*Jupiter::String_Type::str) == towupper(in);
-}
-
-template bool Jupiter::String_Type