#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 storedWordsCount could be > count 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::insertSortedPos(int index, int value) { if (index == -1) index = count; for (int i = count; i > index; i--) sortedPos[i] = sortedPos[i - 1]; sortedPos[index] = value; } void WordCollection::removeSortedPos(int index) { for (int i = index; i <= count - 2; i++) sortedPos[i] = sortedPos[i + 1]; sortedPos[count - 1] = 0; } int WordCollection::findSortedPosIndexFirstBigger(const char* str) const { for (int i = 0; i < count; i++) { if (words[sortedPos[i]].compare(str) > 0) return i; } return -1; } int WordCollection::findSortedPosIndex(const char* str) const { int l = 0, r = count - 1; while (l <= r) { int m = (l + r) / 2; int cmp = words[sortedPos[m]].compare(str); if (cmp > 0) r = m - 1; else if (cmp < 0) l = m + 1; else return m; } 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) { if (this != &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); insertSortedPos(findSortedPosIndexFirstBigger(str), storedWordsCount); count++; storedWordsCount++; } return *this; } WordCollection& WordCollection::operator/=(const char* str) { int ind = findSortedPosIndex(str); if (ind > -1) { words[sortedPos[ind]] = DynStr(); removeSortedPos(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) const { return findSortedPosIndex(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; }