diff --git a/Jupiter/Shift_String.h b/Jupiter/Shift_String.h index c030286..03882dd 100644 --- a/Jupiter/Shift_String.h +++ b/Jupiter/Shift_String.h @@ -60,7 +60,15 @@ namespace Jupiter * @param value Value of the element to remove. * @return True if an element was removed, false otherwise. */ - virtual bool remove(const T &value); + virtual bool remove(const T &value) override; + + /** + * @brief Removes a number of elements starting at an index. + * + * @param index Index to start removing elements at. + * @param length Number of elements to remove. + */ + virtual void remove(size_t index, size_t length) override; /** * @brief Default constructor for the Shift_String_Type class. diff --git a/Jupiter/Shift_String_Imp.h b/Jupiter/Shift_String_Imp.h index 6fda85b..7a88645 100644 --- a/Jupiter/Shift_String_Imp.h +++ b/Jupiter/Shift_String_Imp.h @@ -64,6 +64,14 @@ template bool Jupiter::Shift_String_Type::remove(const T &value) return Jupiter::String_Type::remove(value); } +template void Jupiter::Shift_String_Type::remove(size_t index, size_t length) +{ + if (index == 0) + this->shiftRight(length); + else + Jupiter::String_Type::remove(index, length); +} + template bool Jupiter::Shift_String_Type::setBufferSize(size_t len) { if (len > Jupiter::String_Type::length) diff --git a/Jupiter/String_Type.h b/Jupiter/String_Type.h index 27a6401..2e31cbd 100644 --- a/Jupiter/String_Type.h +++ b/Jupiter/String_Type.h @@ -102,6 +102,20 @@ namespace Jupiter */ virtual bool remove(const T &value); + /** + * @brief Removes a number of elements starting at an index. + * + * @param index Index to start removing elements at. + * @param length Number of elements to remove. + */ + virtual void remove(size_t index, size_t length); + + /** + * @brief Processes escape sequences in a string. + * Source reference: http://en.cppreference.com/w/cpp/language/escape + */ + virtual void processEscapeSequences(); + /** * @brief Sets the value of an element at the specified index. * Note: If the index is not in the string, it will be added. @@ -137,6 +151,18 @@ namespace Jupiter virtual size_t insert(size_t index, const T &value); virtual size_t insert(size_t index, const Jupiter::Readable_String &value); + /** + * @brief Replaces data at an index with a specified value. + * + * @param index Index to start replacing at. + * @param length Number of elements to replace. + * @param value Value to write over the elements. + * @return New size of the string. + */ + virtual size_t replace(size_t index, size_t length, const T &value); + virtual size_t replace(size_t index, size_t length, const T *value, size_t valueSize); + virtual size_t replace(size_t index, size_t length, const Jupiter::Readable_String &value); + /** * @brief Replaces all instances of one value with another value. * diff --git a/Jupiter/String_Type_Imp.h b/Jupiter/String_Type_Imp.h index 4b91d87..910732b 100644 --- a/Jupiter/String_Type_Imp.h +++ b/Jupiter/String_Type_Imp.h @@ -132,14 +132,197 @@ template bool Jupiter::String_Type::remove(const T &value) return false; } +template void Jupiter::String_Type::remove(size_t index, size_t length) +{ + if (index >= Jupiter::String_Type::length) + return; + + if (index + length >= Jupiter::String_Type::length) + Jupiter::String_Type::length = index; + else + { + Jupiter::String_Type::length -= length; + length += index; + + Jupiter::String_Type::str[index] = Jupiter::String_Type::str[length]; + while (++index != Jupiter::String_Type::length) + Jupiter::String_Type::str[index] = Jupiter::String_Type::str[++length]; + } +} + +// processEscapeSequences + +template void Jupiter::String_Type::processEscapeSequences() +{ +} + +template<> inline void Jupiter::String_Type::processEscapeSequences() +{ + if (Jupiter::String_Type::length == 0) + return; + + size_t index = 0; + while (index + 1 != Jupiter::String_Type::length) + { + printf("Processing: %c (%u) @ %u" ENDL, this->get(index), this->get(index), index); + if (this->get(index) == '\\') + { + switch (this->get(++index)) + { + case '0': + case '1': + case '2': + case '3': + if (index + 1 != Jupiter::String_Type::length && Jupiter_isBase(this->get(index + 1), 8)) + { + if (index + 2 != Jupiter::String_Type::length && Jupiter_isBase(this->get(index + 2), 8)) + this->replace(index - 1, 4, static_cast(Jupiter_getBase(this->get(index), 8)) << 6 | static_cast(Jupiter_getBase(this->get(index + 1), 8)) << 3 | static_cast(Jupiter_getBase(this->get(index + 2), 8))); + else + this->replace(index - 1, 3, static_cast(Jupiter_getBase(this->get(index), 8)) << 3 | static_cast(Jupiter_getBase(this->get(index + 1), 8))); + } + else + this->replace(index - 1, 2, static_cast(Jupiter_getBase(this->get(index), 8))); + break; + case '4': + case '5': + case '6': + case '7': + if (index + 1 != Jupiter::String_Type::length && Jupiter_isBase(this->get(index + 1), 8)) + this->replace(index - 1, 3, static_cast(Jupiter_getBase(this->get(index), 8)) << 3 | static_cast(Jupiter_getBase(this->get(index + 1), 8))); + else + this->replace(index - 1, 2, static_cast(Jupiter_getBase(this->get(index), 8))); + break; + case 'a': + this->replace(index - 1, 2, '\a'); + break; + case 'b': + this->replace(index - 1, 2, '\b'); + break; + case 'f': + this->replace(index - 1, 2, '\f'); + break; + case 'n': + this->replace(index - 1, 2, '\n'); + break; + case 'r': + this->replace(index - 1, 2, '\r'); + break; + case 't': + this->replace(index - 1, 2, '\t'); + break; + case 'v': + this->replace(index - 1, 2, '\v'); + break; + case '?': + this->replace(index - 1, 2, '\?'); + break; + case '\'': + this->replace(index - 1, 2, '\''); + break; + case '\"': + this->replace(index - 1, 2, '\"'); + break; + case '\\': + this->replace(index - 1, 2, '\\'); + break; + case 'x': + if (Jupiter::String_Type::length >= index + 2 + && Jupiter_isBase(this->get(index + 1), 16) && Jupiter_isBase(this->get(index + 2), 16)) + this->replace(index - 1, 4, static_cast(Jupiter_getBase(this->get(index + 1), 16)) << 4 | static_cast(Jupiter_getBase(this->get(index + 2), 16))); + break; + case 'U': + if (Jupiter::String_Type::length >= index + 8 + && Jupiter_isBase(this->get(index + 1), 16) && Jupiter_isBase(this->get(index + 2), 16) && Jupiter_isBase(this->get(index + 3), 16) && Jupiter_isBase(this->get(index + 4), 16) && Jupiter_isBase(this->get(index + 5), 16) && Jupiter_isBase(this->get(index + 6), 16) && Jupiter_isBase(this->get(index + 7), 16) && Jupiter_isBase(this->get(index + 8), 16)) + { + uint32_t codepoint = static_cast(Jupiter_getBase(this->get(index + 1), 16)) << 4 | static_cast(Jupiter_getBase(this->get(index + 2), 16)); + codepoint <<= 8; + codepoint |= static_cast(Jupiter_getBase(this->get(index + 3), 16)) << 4 | static_cast(Jupiter_getBase(this->get(index + 4), 16)); + codepoint <<= 8; + codepoint |= static_cast(Jupiter_getBase(this->get(index + 5), 16)) << 4 | static_cast(Jupiter_getBase(this->get(index + 6), 16)); + codepoint <<= 8; + codepoint |= static_cast(Jupiter_getBase(this->get(index + 7), 16)) << 4 | static_cast(Jupiter_getBase(this->get(index + 8), 16)); + if (codepoint <= 0x007F) + this->replace(index - 1, 10, static_cast(codepoint)); + else if (codepoint <= 0x07FF) + { + char bytes[2]; + bytes[0] = 0xC0 | ((codepoint >> 6) & 0x1F); + bytes[1] = 0x80 | (codepoint & 0x3F); + this->replace(index - 1, 10, bytes, sizeof(bytes)); + ++index; + } + else if (codepoint <= 0xFFFF) + { + char bytes[3]; + bytes[0] = 0xE0 | ((codepoint >> 12) & 0x0F); + bytes[1] = 0x80 | ((codepoint >> 6) & 0x3F); + bytes[2] = 0x80 | (codepoint & 0x3F); + this->replace(index - 1, 10, bytes, sizeof(bytes)); + index += 2; + } + else if (codepoint <= 0x10FFFF) + { + char bytes[4]; + bytes[0] = 0xE0 | ((codepoint >> 18) & 0x0F); + bytes[1] = 0x80 | ((codepoint >> 12) & 0x3F); + bytes[2] = 0x80 | ((codepoint >> 6) & 0x3F); + bytes[3] = 0x80 | (codepoint & 0x3F); + this->replace(index - 1, 10, bytes, sizeof(bytes)); + index += 3; + } + } + break; + case 'u': + if (Jupiter::String_Type::length >= index + 4 + && Jupiter_isBase(this->get(index + 1), 16) && Jupiter_isBase(this->get(index + 2), 16) && Jupiter_isBase(this->get(index + 3), 16) && Jupiter_isBase(this->get(index + 4), 16)) + { + uint16_t codepoint = static_cast(Jupiter_getBase(this->get(index + 1), 16)) << 4 | static_cast(Jupiter_getBase(this->get(index + 2), 16)); + codepoint <<= 8; + codepoint |= static_cast(Jupiter_getBase(this->get(index + 3), 16)) << 4 | static_cast(Jupiter_getBase(this->get(index + 4), 16)); + if (codepoint <= 0x007F) + this->replace(index - 1, 6, static_cast(codepoint)); + else if (codepoint <= 0x07FF) + { + char bytes[2]; + bytes[0] = 0xC0 | ((codepoint >> 6) & 0x1F); + bytes[1] = 0x80 | (codepoint & 0x3F); + this->replace(index - 1, 6, bytes, sizeof(bytes)); + ++index; + } + else if (codepoint <= 0xFFFF) + { + char bytes[3]; + bytes[0] = 0xE0 | ((codepoint >> 12) & 0x0F); + bytes[1] = 0x80 | ((codepoint >> 6) & 0x3F); + bytes[2] = 0x80 | (codepoint & 0x3F); + this->replace(index - 1, 6, bytes, sizeof(bytes)); + index += 2; + } + } + break; + default: + break; + } + if (index == Jupiter::String_Type::length) + break; + } + else + ++index; + } +} + +template<> inline void Jupiter::String_Type::processEscapeSequences() +{ +} + // set template size_t Jupiter::String_Type::set(size_t index, const T &in) { - if (index == this->size()) + if (index == Jupiter::String_Type::length) return this->concat(in); - if (index > this->size()) + if (index > Jupiter::String_Type::length) { this->setBufferSize(index + 1); while (Jupiter::String_Type::length != index) @@ -152,10 +335,10 @@ template size_t Jupiter::String_Type::set(size_t index, const T & template size_t Jupiter::String_Type::set(size_t index, const T *in, size_t inSize) { - if (index == this->size()) + if (index == Jupiter::String_Type::length) return this->concat(in); - if (index > this->size()) + if (index > Jupiter::String_Type::length) { this->setBufferSize(index + inSize); while (Jupiter::String_Type::length != index) @@ -225,15 +408,15 @@ template size_t Jupiter::String_Type::set(const T &in) return Jupiter::String_Type::length = 1; } -// replace +// insert template size_t Jupiter::String_Type::insert(size_t index, const T &value) { - if (index >= this->size()) + if (index >= Jupiter::String_Type::length) return this->concat(value); - this->setBufferSize(this->size() + 1); - for (size_t i = this->size(); i != index; i--) + this->setBufferSize(Jupiter::String_Type::length + 1); + for (size_t i = Jupiter::String_Type::length; i != index; i--) Jupiter::String_Type::str[i] = this->get(i-1); Jupiter::String_Type::str[index] = value; @@ -242,7 +425,7 @@ template size_t Jupiter::String_Type::insert(size_t index, const template size_t Jupiter::String_Type::insert(size_t index, const Jupiter::Readable_String &value) { - if (index >= this->size()) + if (index >= Jupiter::String_Type::length) return this->concat(value); if (value.size() == 0) @@ -251,9 +434,9 @@ template size_t Jupiter::String_Type::insert(size_t index, const if (value.size() == 1) return this->insert(index, value.get(0)); - this->setBufferSize(this->size() + value.size()); + this->setBufferSize(Jupiter::String_Type::length + value.size()); size_t i; - for (i = this->size() + value.size() - 1; i != index + value.size() - 1; i--) + for (i = Jupiter::String_Type::length + value.size() - 1; i != index + value.size() - 1; i--) Jupiter::String_Type::str[i] = this->get(i - value.size()); while (i != index) @@ -268,9 +451,99 @@ template size_t Jupiter::String_Type::insert(size_t index, const // replace +template size_t Jupiter::String_Type::replace(size_t index, size_t targetSize, const T &value) +{ + if (targetSize != 0) + { + if (index >= Jupiter::String_Type::length) + return this->set(index, value); + + if (index + targetSize > Jupiter::String_Type::length) + { + Jupiter::String_Type::str[index] = value; + return Jupiter::String_Type::length = index + 1; + } + + if (targetSize == 1) + return this->set(index, value); + + Jupiter::String_Type::str[index] = value; + Jupiter::String_Type::length -= targetSize - 1; + while (++index != Jupiter::String_Type::length) + Jupiter::String_Type::str[index] = Jupiter::String_Type::str[index + targetSize - 1]; + } + return Jupiter::String_Type::length; +} + +template size_t Jupiter::String_Type::replace(size_t index, size_t targetSize, const T *value, size_t valueSize) +{ + if (valueSize == 1) + return this->replace(index, targetSize, *value); + + if (valueSize == 0) + { + this->remove(index, targetSize); + return Jupiter::String_Type::length; + } + + if (targetSize != 0) + { + if (index >= Jupiter::String_Type::length) + return this->set(index, value); + + if (index + targetSize > Jupiter::String_Type::length) + { + if (index + valueSize > Jupiter::String_Type::length) + this->setBufferSize(index + valueSize); + + Jupiter::String_Type::length = index + valueSize; + Jupiter::String_Type::str[index] = *value; + while (++index != Jupiter::String_Type::length) + Jupiter::String_Type::str[index] = *++value; + return Jupiter::String_Type::length; + } + + if (targetSize == valueSize) + return this->set(index, value, valueSize); + + if (valueSize < targetSize) + { + targetSize -= valueSize; + Jupiter::String_Type::length -= targetSize; + + Jupiter::String_Type::str[index] = *value; + while (--valueSize != 0) + Jupiter::String_Type::str[++index] = *++value; + + while (++index != Jupiter::String_Type::length) + Jupiter::String_Type::str[index] = Jupiter::String_Type::str[index + targetSize]; + } + else + { + this->setBufferSize(Jupiter::String_Type::length + valueSize - targetSize); + Jupiter::String_Type::length += valueSize - targetSize; + + size_t i = Jupiter::String_Type::length; + while (--i != index + targetSize + 1) + Jupiter::String_Type::str[i] = Jupiter::String_Type::str[i - valueSize + targetSize]; + this->println(stdout); + + Jupiter::String_Type::str[index] = *value; + while (index != i) + Jupiter::String_Type::str[++index] = *++value; + } + } + return Jupiter::String_Type::length; +} + +template size_t Jupiter::String_Type::replace(size_t index, size_t targetSize, const Jupiter::Readable_String &value) +{ + return this->replace(index, targetSize, value.ptr(), value.size()); +} + template size_t Jupiter::String_Type::replace(const T &target, const T &value) { - for (size_t i = 0; i != this->size(); i++) + for (size_t i = 0; i != Jupiter::String_Type::length; i++) { if (this->get(i) == target) Jupiter::String_Type::str[i] = value; @@ -285,10 +558,10 @@ template size_t Jupiter::String_Type::replace(const T *target, si if (targetSize == 1) return this->replace(*target, value); - if (targetSize < this->size()) + if (targetSize < Jupiter::String_Type::length) { size_t i = 0, j = 0, k; - while (j <= this->size() - targetSize) + while (j <= Jupiter::String_Type::length - targetSize) { k = 0; while (this->get(j + k) == target[k]) @@ -304,12 +577,12 @@ template size_t Jupiter::String_Type::replace(const T *target, si if (k != targetSize) Jupiter::String_Type::str[i++] = Jupiter::String_Type::str[j++]; } - while (j < this->size()) + while (j < Jupiter::String_Type::length) Jupiter::String_Type::str[i++] = Jupiter::String_Type::str[j++]; Jupiter::String_Type::length = i; } - else if (targetSize == this->size() && this->equals(target, targetSize)) + else if (targetSize == Jupiter::String_Type::length && this->equals(target, targetSize)) return this->set(value); } return Jupiter::String_Type::length; @@ -330,7 +603,7 @@ template size_t Jupiter::String_Type::replace(const T *target, si //if (targetSize == 1) // return this->replace(*target, value, valueSize); - if (targetSize < this->size()) + if (targetSize < Jupiter::String_Type::length) { if (valueSize > targetSize) { @@ -338,7 +611,7 @@ template size_t Jupiter::String_Type::replace(const T *target, si size_t *instances = new size_t[instancesSize]; // pass 1 (count instances) size_t instanceCount = 0, i = 0, j; - while (i <= this->size() - targetSize) + while (i <= Jupiter::String_Type::length - targetSize) { j = 0; while (this->get(i + j) == target[j]) @@ -367,7 +640,7 @@ template size_t Jupiter::String_Type::replace(const T *target, si if (instanceCount != 0) { // pass 2 (adjust string and replace values) - size_t endSize = this->size() + (valueSize - targetSize) * instanceCount; + size_t endSize = Jupiter::String_Type::length + (valueSize - targetSize) * instanceCount; this->setBufferSize(endSize); instancesSize = endSize; // Repurposing. Now used as just another index. j = Jupiter::String_Type::length; @@ -389,7 +662,7 @@ template size_t Jupiter::String_Type::replace(const T *target, si else { size_t i = 0, j = 0, k, l; - while (j <= this->size() - targetSize) + while (j <= Jupiter::String_Type::length - targetSize) { k = 0; while (this->get(j + k) == target[k]) @@ -406,13 +679,13 @@ template size_t Jupiter::String_Type::replace(const T *target, si if (k != targetSize) Jupiter::String_Type::str[i++] = Jupiter::String_Type::str[j++]; } - while (j < this->size()) + while (j < Jupiter::String_Type::length) Jupiter::String_Type::str[i++] = Jupiter::String_Type::str[j++]; Jupiter::String_Type::length = i; } } - else if (targetSize == this->size() && this->equals(target, targetSize)) + else if (targetSize == Jupiter::String_Type::length && this->equals(target, targetSize)) return this->set(value); } return Jupiter::String_Type::length; diff --git a/Release/Jupiter.lib b/Release/Jupiter.lib index 086f99e..276bc80 100644 Binary files a/Release/Jupiter.lib and b/Release/Jupiter.lib differ