#include "WordCollection.h" #include "cstring" #include /* Private */ void WordCollection::free() { delete[] words; delete[] sortMap; } void WordCollection::copyFrom(const WordCollection& other) { sortMapCount = other.sortMapCount; wordsCount = other.wordsCount; length = other.length; words = new DynStr[length]; sortMap = new int[length]; for (int i = 0; i < length; i++) { // Must be < length, since we can have valid items outside the count range in words words[i] = other.words[i]; sortMap[i] = other.sortMap[i]; } } void WordCollection::resize() { int oldLength = length; if (length == 0) length = 8; else length <<= 1; DynStr* newWords = new DynStr[length]; int* newSortMap = new int[length]; for (int i = 0; i < oldLength; i++) { newWords[i] = words[i]; newSortMap[i] = sortMap[i]; } delete[] words; delete[] sortMap; words = newWords; sortMap = newSortMap; } void WordCollection::insertSortMapIndex(int position, int value) { if (position == -1) position = sortMapCount; for (int i = sortMapCount; i > position; i--) sortMap[i] = sortMap[i - 1]; sortMap[position] = value; } void WordCollection::removeSortMapIndex(int position) { for (int i = position; i <= sortMapCount - 2; i++) sortMap[i] = sortMap[i + 1]; sortMap[sortMapCount - 1] = 0; } int WordCollection::findSortMapIndexWhen(int condition, const char* str) { if (condition < -1) condition = -1; else if (condition > 1) condition = 1; // TODO: replace with binary search for (int i = 0; i < sortMapCount; i++) { int cmp = strcmp(words[sortMap[i]].get_str(), str); if (cmp > 1) cmp = 1; else if (cmp < -1) cmp = -1; if (cmp == condition) return i; } return -1; } /* Public */ WordCollection::WordCollection() { words = nullptr; sortMap = nullptr; sortMapCount = wordsCount = length = 0; } WordCollection::WordCollection(const WordCollection& other) { copyFrom(other); } WordCollection& WordCollection::operator=(const WordCollection& other) { if (this != &other) { free(); copyFrom(other); } return *this; } WordCollection::~WordCollection() { free(); } WordCollection& WordCollection::operator+=(const WordCollection& other) { for (int i = 0; i < other.sortMapCount; i++) { (*this) *= other.words[other.sortMap[i]].get_str(); } return *this; } WordCollection& WordCollection::operator-=(const WordCollection& other) { if (this != &other) { for (int i = 0; i < other.sortMapCount; i++) { (*this) /= other.words[other.sortMap[i]].get_str(); } } else { *this = WordCollection(); } return *this; } WordCollection& WordCollection::operator*=(const char* str) { if (!(*this)[str]) { if (sortMapCount == length || wordsCount == length) resize(); words[wordsCount] = DynStr(str); insertSortMapIndex(findSortMapIndexWhen(1, str), wordsCount); sortMapCount++; wordsCount++; } return *this; } WordCollection& WordCollection::operator/=(const char* str) { int ind = findSortMapIndexWhen(0, str); if (ind > -1) { words[sortMap[ind]] = DynStr(); removeSortMapIndex(ind); sortMapCount--; } return *this; } std::ostream& operator<<(std::ostream& ostrm, const WordCollection& collection) { ostrm << "{"; if (collection.sortMapCount > 0) { for (int i = 0; i <= collection.sortMapCount - 2; i++) ostrm << collection.words[collection.sortMap[i]].get_str() << ", "; ostrm << collection.words[collection.sortMap[collection.sortMapCount - 1]].get_str(); } ostrm << "}"; return ostrm; } std::istream& operator>>(std::istream& istrm, WordCollection& collection) { char buffer[1024]; istrm.getline(buffer, 1024); collection *= buffer; return istrm; } bool WordCollection::operator[](const char* str) { return findSortMapIndexWhen(0, str) > -1; } const WordCollection operator+(const WordCollection& lhs, const WordCollection& rhs) { WordCollection res(lhs); res += rhs; return res; } const WordCollection operator-(const WordCollection& lhs, const WordCollection& rhs) { WordCollection res(lhs); res -= rhs; return res; }