#include "WordCollection.h" #include "cstring" #include /* Private */ void WordCollection::free() { delete[] words; delete[] sortedPos; } void WordCollection::copyFrom(const WordCollection& other) { count = other.count; storedWordsCount = other.storedWordsCount; length = other.length; words = new DynStr[length]; sortedPos = 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]; sortedPos[i] = other.sortedPos[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] = sortedPos[i]; } delete[] words; delete[] sortedPos; words = newWords; sortedPos = newSortMap; } void WordCollection::insertSortMapIndex(int position, int value) { if (position == -1) position = count; for (int i = count; i > position; i--) sortedPos[i] = sortedPos[i - 1]; sortedPos[position] = value; } void WordCollection::removeSortMapIndex(int position) { for (int i = position; i <= count - 2; i++) sortedPos[i] = sortedPos[i + 1]; sortedPos[count - 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 < count; i++) { if (words[sortedPos[i]].compare(str) == condition) return i; } return -1; } /* Public */ WordCollection::WordCollection() { words = nullptr; sortedPos = nullptr; count = storedWordsCount = 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.count; i++) { (*this) *= other.words[other.sortedPos[i]].get_str(); } return *this; } WordCollection& WordCollection::operator-=(const WordCollection& other) { if (this != &other) { for (int i = 0; i < other.count; i++) { (*this) /= other.words[other.sortedPos[i]].get_str(); } } else { *this = WordCollection(); } return *this; } WordCollection& WordCollection::operator*=(const char* str) { if (!(*this)[str]) { if (count == length || storedWordsCount == length) resize(); words[storedWordsCount] = DynStr(str); insertSortMapIndex(findSortMapIndexWhen(1, str), storedWordsCount); count++; storedWordsCount++; } return *this; } WordCollection& WordCollection::operator/=(const char* str) { int ind = findSortMapIndexWhen(0, str); if (ind > -1) { words[sortedPos[ind]] = DynStr(); removeSortMapIndex(ind); count--; } return *this; } std::ostream& operator<<(std::ostream& ostrm, const WordCollection& collection) { ostrm << "{"; if (collection.count > 0) { for (int i = 0; i <= collection.count - 2; i++) ostrm << collection.words[collection.sortedPos[i]].get_str() << ", "; ostrm << collection.words[collection.sortedPos[collection.count - 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; }