diff options
Diffstat (limited to 'source/core/slang-string.cpp')
| -rw-r--r-- | source/core/slang-string.cpp | 1101 |
1 files changed, 566 insertions, 535 deletions
diff --git a/source/core/slang-string.cpp b/source/core/slang-string.cpp index 182c6261e..b58d466fa 100644 --- a/source/core/slang-string.cpp +++ b/source/core/slang-string.cpp @@ -1,288 +1,292 @@ #include "slang-string.h" -#include "slang-text-io.h" #include "slang-char-util.h" +#include "slang-text-io.h" namespace Slang { - // HACK! - // JS: Many of the inlined functions of CharUtil just access a global map. That referencing this global is *NOT* enough to - // link correctly with CharUtil on linux for a shared library. The following call exists to try and force linkage of CharUtil - // for anything that uses core - static const auto s_charUtilLink = CharUtil::_ensureLink(); +// HACK! +// JS: Many of the inlined functions of CharUtil just access a global map. That referencing this +// global is *NOT* enough to link correctly with CharUtil on linux for a shared library. The +// following call exists to try and force linkage of CharUtil for anything that uses core +static const auto s_charUtilLink = CharUtil::_ensureLink(); - // StringRepresentation +// StringRepresentation - void StringRepresentation::setContents(const UnownedStringSlice& slice) - { - const auto sliceLength = slice.getLength(); - SLANG_ASSERT(sliceLength <= capacity); +void StringRepresentation::setContents(const UnownedStringSlice& slice) +{ + const auto sliceLength = slice.getLength(); + SLANG_ASSERT(sliceLength <= capacity); - char* chars = getData(); + char* chars = getData(); - // Use move (rather than memcpy), because the slice *could* be contained in the StringRepresentation - ::memmove(chars, slice.begin(), sliceLength * sizeof(char)); - // Zero terminate. - chars[sliceLength] = 0; - // Set the length - length = sliceLength; - } + // Use move (rather than memcpy), because the slice *could* be contained in the + // StringRepresentation + ::memmove(chars, slice.begin(), sliceLength * sizeof(char)); + // Zero terminate. + chars[sliceLength] = 0; + // Set the length + length = sliceLength; +} - /* static */StringRepresentation* StringRepresentation::create(const UnownedStringSlice& slice) +/* static */ StringRepresentation* StringRepresentation::create(const UnownedStringSlice& slice) +{ + const auto sliceLength = slice.getLength(); + + if (sliceLength) { - const auto sliceLength = slice.getLength(); + StringRepresentation* rep = StringRepresentation::createWithLength(sliceLength); - if (sliceLength) - { - StringRepresentation* rep = StringRepresentation::createWithLength(sliceLength); - - char* chars = rep->getData(); - ::memcpy(chars, slice.begin(), sizeof(char) * sliceLength); - chars[sliceLength] = 0; + char* chars = rep->getData(); + ::memcpy(chars, slice.begin(), sizeof(char) * sliceLength); + chars[sliceLength] = 0; - return rep; - } - else - { - return nullptr; - } + return rep; } - - /* static */StringRepresentation* StringRepresentation::createWithReference(const UnownedStringSlice& slice) + else { - const auto sliceLength = slice.getLength(); + return nullptr; + } +} - if (sliceLength) - { - StringRepresentation* rep = StringRepresentation::createWithLength(sliceLength); - rep->addReference(); +/* static */ StringRepresentation* StringRepresentation::createWithReference( + const UnownedStringSlice& slice) +{ + const auto sliceLength = slice.getLength(); - char* chars = rep->getData(); - ::memcpy(chars, slice.begin(), sizeof(char) * sliceLength); - chars[sliceLength] = 0; + if (sliceLength) + { + StringRepresentation* rep = StringRepresentation::createWithLength(sliceLength); + rep->addReference(); - return rep; - } - else - { - return nullptr; - } + char* chars = rep->getData(); + ::memcpy(chars, slice.begin(), sizeof(char) * sliceLength); + chars[sliceLength] = 0; + + return rep; } + else + { + return nullptr; + } +} - // OSString +// OSString - OSString::OSString() - : m_begin(nullptr) - , m_end(nullptr) - {} +OSString::OSString() + : m_begin(nullptr), m_end(nullptr) +{ +} - OSString::OSString(wchar_t* begin, wchar_t* end) - : m_begin(begin) - , m_end(end) - {} +OSString::OSString(wchar_t* begin, wchar_t* end) + : m_begin(begin), m_end(end) +{ +} - void OSString::_releaseBuffer() +void OSString::_releaseBuffer() +{ + if (m_begin) { - if (m_begin) - { - delete[] m_begin; - } + delete[] m_begin; } +} - void OSString::set(const wchar_t* begin, const wchar_t* end) +void OSString::set(const wchar_t* begin, const wchar_t* end) +{ + if (m_begin) { - if (m_begin) - { - delete[] m_begin; - m_begin = nullptr; - m_end = nullptr; - } - const size_t len = end - begin; - if (len > 0) - { - // TODO(JS): The allocation is only done this way to be compatible with the buffer being detached from an array - // This is unfortunate, because it means that the allocation stores the size (and alignment fix), which is a shame because we know the size - m_begin = new wchar_t[len + 1]; - memcpy(m_begin, begin, len * sizeof(wchar_t)); - // Zero terminate - m_begin[len] = 0; - m_end = m_begin + len; - } + delete[] m_begin; + m_begin = nullptr; + m_end = nullptr; } - - static const wchar_t kEmptyOSString[] = { 0 }; - - wchar_t const* OSString::begin() const + const size_t len = end - begin; + if (len > 0) { - return m_begin ? m_begin : kEmptyOSString; + // TODO(JS): The allocation is only done this way to be compatible with the buffer being + // detached from an array This is unfortunate, because it means that the allocation stores + // the size (and alignment fix), which is a shame because we know the size + m_begin = new wchar_t[len + 1]; + memcpy(m_begin, begin, len * sizeof(wchar_t)); + // Zero terminate + m_begin[len] = 0; + m_end = m_begin + len; } +} - wchar_t const* OSString::end() const - { - return m_end ? m_end : kEmptyOSString; - } +static const wchar_t kEmptyOSString[] = {0}; - // UnownedStringSlice +wchar_t const* OSString::begin() const +{ + return m_begin ? m_begin : kEmptyOSString; +} - bool UnownedStringSlice::startsWith(UnownedStringSlice const& other) const - { - UInt thisSize = getLength(); - UInt otherSize = other.getLength(); +wchar_t const* OSString::end() const +{ + return m_end ? m_end : kEmptyOSString; +} - if (otherSize > thisSize) - return false; +// UnownedStringSlice - return head(otherSize) == other; - } +bool UnownedStringSlice::startsWith(UnownedStringSlice const& other) const +{ + UInt thisSize = getLength(); + UInt otherSize = other.getLength(); - bool UnownedStringSlice::startsWith(char const* str) const - { - return startsWith(UnownedTerminatedStringSlice(str)); - } + if (otherSize > thisSize) + return false; - bool UnownedStringSlice::startsWithCaseInsensitive(UnownedStringSlice const& other) const - { - UInt thisSize = getLength(); - UInt otherSize = other.getLength(); + return head(otherSize) == other; +} - if (otherSize > thisSize) - return false; +bool UnownedStringSlice::startsWith(char const* str) const +{ + return startsWith(UnownedTerminatedStringSlice(str)); +} - return head(otherSize).caseInsensitiveEquals(other); - } +bool UnownedStringSlice::startsWithCaseInsensitive(UnownedStringSlice const& other) const +{ + UInt thisSize = getLength(); + UInt otherSize = other.getLength(); + if (otherSize > thisSize) + return false; - bool UnownedStringSlice::endsWith(UnownedStringSlice const& other) const - { - UInt thisSize = getLength(); - UInt otherSize = other.getLength(); + return head(otherSize).caseInsensitiveEquals(other); +} - if (otherSize > thisSize) - return false; - return UnownedStringSlice( - end() - otherSize, end()) == other; - } +bool UnownedStringSlice::endsWith(UnownedStringSlice const& other) const +{ + UInt thisSize = getLength(); + UInt otherSize = other.getLength(); - bool UnownedStringSlice::endsWithCaseInsensitive(UnownedStringSlice const& other) const - { - UInt thisSize = getLength(); - UInt otherSize = other.getLength(); + if (otherSize > thisSize) + return false; - if (otherSize > thisSize) - return false; + return UnownedStringSlice(end() - otherSize, end()) == other; +} - return UnownedStringSlice(end() - otherSize, end()).caseInsensitiveEquals(other); - } +bool UnownedStringSlice::endsWithCaseInsensitive(UnownedStringSlice const& other) const +{ + UInt thisSize = getLength(); + UInt otherSize = other.getLength(); - bool UnownedStringSlice::endsWith(char const* str) const - { - return endsWith(UnownedTerminatedStringSlice(str)); - } + if (otherSize > thisSize) + return false; - bool UnownedStringSlice::endsWithCaseInsensitive(char const* str) const - { - return endsWithCaseInsensitive(UnownedTerminatedStringSlice(str)); - } + return UnownedStringSlice(end() - otherSize, end()).caseInsensitiveEquals(other); +} - UnownedStringSlice UnownedStringSlice::trim() const - { - const char* start = m_begin; - const char* end = m_end; +bool UnownedStringSlice::endsWith(char const* str) const +{ + return endsWith(UnownedTerminatedStringSlice(str)); +} - while (start < end && CharUtil::isHorizontalWhitespace(*start)) start++; - while (end > start && CharUtil::isHorizontalWhitespace(end[-1])) end--; - return UnownedStringSlice(start, end); - } +bool UnownedStringSlice::endsWithCaseInsensitive(char const* str) const +{ + return endsWithCaseInsensitive(UnownedTerminatedStringSlice(str)); +} - UnownedStringSlice UnownedStringSlice::trimStart() const - { - const char* start = m_begin; +UnownedStringSlice UnownedStringSlice::trim() const +{ + const char* start = m_begin; + const char* end = m_end; + + while (start < end && CharUtil::isHorizontalWhitespace(*start)) + start++; + while (end > start && CharUtil::isHorizontalWhitespace(end[-1])) + end--; + return UnownedStringSlice(start, end); +} - while (start < m_end && CharUtil::isHorizontalWhitespace(*start)) start++; - return UnownedStringSlice(start, m_end); - } +UnownedStringSlice UnownedStringSlice::trimStart() const +{ + const char* start = m_begin; - UnownedStringSlice UnownedStringSlice::trim(char c) const - { - const char* start = m_begin; - const char* end = m_end; + while (start < m_end && CharUtil::isHorizontalWhitespace(*start)) + start++; + return UnownedStringSlice(start, m_end); +} - while (start < end && *start == c) start++; - while (end > start && end[-1] == c) end--; - return UnownedStringSlice(start, end); - } +UnownedStringSlice UnownedStringSlice::trim(char c) const +{ + const char* start = m_begin; + const char* end = m_end; + + while (start < end && *start == c) + start++; + while (end > start && end[-1] == c) + end--; + return UnownedStringSlice(start, end); +} - // StringSlice +// StringSlice - StringSlice::StringSlice() - : representation(0) - , beginIndex(0) - , endIndex(0) - {} +StringSlice::StringSlice() + : representation(0), beginIndex(0), endIndex(0) +{ +} - StringSlice::StringSlice(String const& str) - : representation(str.m_buffer) - , beginIndex(0) - , endIndex(str.getLength()) - {} +StringSlice::StringSlice(String const& str) + : representation(str.m_buffer), beginIndex(0), endIndex(str.getLength()) +{ +} - StringSlice::StringSlice(String const& str, UInt beginIndex, UInt endIndex) - : representation(str.m_buffer) - , beginIndex(beginIndex) - , endIndex(endIndex) - {} +StringSlice::StringSlice(String const& str, UInt beginIndex, UInt endIndex) + : representation(str.m_buffer), beginIndex(beginIndex), endIndex(endIndex) +{ +} - // +// - _EndLine EndLine; +_EndLine EndLine; - String operator+(const char * op1, const String & op2) - { - String result(op1); - result.append(op2); - return result; - } +String operator+(const char* op1, const String& op2) +{ + String result(op1); + result.append(op2); + return result; +} - String operator+(const String & op1, const char * op2) - { - String result(op1); - result.append(op2); - return result; - } +String operator+(const String& op1, const char* op2) +{ + String result(op1); + result.append(op2); + return result; +} - String operator+(const String & op1, const String & op2) - { - String result(op1); - result.append(op2); - return result; - } +String operator+(const String& op1, const String& op2) +{ + String result(op1); + result.append(op2); + return result; +} - int stringToInt(const String& str, int radix) - { - if (str.startsWith("0x")) - return (int)strtoll(str.getBuffer(), NULL, 16); - else - return (int)strtoll(str.getBuffer(), NULL, radix); - } - unsigned int stringToUInt(const String& str, int radix) - { - if (str.startsWith("0x")) - return (unsigned int)strtoull(str.getBuffer(), NULL, 16); - else - return (unsigned int)strtoull(str.getBuffer(), NULL, radix); - } - double stringToDouble(const String& str) - { - return (double)strtod(str.getBuffer(), NULL); - } - float stringToFloat(const String& str) - { - return strtof(str.getBuffer(), NULL); - } +int stringToInt(const String& str, int radix) +{ + if (str.startsWith("0x")) + return (int)strtoll(str.getBuffer(), NULL, 16); + else + return (int)strtoll(str.getBuffer(), NULL, radix); +} +unsigned int stringToUInt(const String& str, int radix) +{ + if (str.startsWith("0x")) + return (unsigned int)strtoull(str.getBuffer(), NULL, 16); + else + return (unsigned int)strtoull(str.getBuffer(), NULL, radix); +} +double stringToDouble(const String& str) +{ + return (double)strtod(str.getBuffer(), NULL); +} +float stringToFloat(const String& str) +{ + return strtof(str.getBuffer(), NULL); +} #if 0 String String::ReplaceAll(String src, String dst) const @@ -300,446 +304,473 @@ namespace Slang } #endif - String String::fromWString(const wchar_t* wstr) - { - List<char> buf; +String String::fromWString(const wchar_t* wstr) +{ + List<char> buf; #ifdef _WIN32 - Slang::CharEncoding::UTF16->decode((const Byte*)wstr, (int)(wcslen(wstr) * sizeof(wchar_t)), buf); + Slang::CharEncoding::UTF16->decode( + (const Byte*)wstr, + (int)(wcslen(wstr) * sizeof(wchar_t)), + buf); #else - Slang::CharEncoding::UTF32->decode((const Byte*)wstr, (int)(wcslen(wstr) * sizeof(wchar_t)), buf); + Slang::CharEncoding::UTF32->decode( + (const Byte*)wstr, + (int)(wcslen(wstr) * sizeof(wchar_t)), + buf); #endif - return String(buf.begin(), buf.end()); - } + return String(buf.begin(), buf.end()); +} - String String::fromWString(const wchar_t* wstr, const wchar_t* wend) - { - List<char> buf; +String String::fromWString(const wchar_t* wstr, const wchar_t* wend) +{ + List<char> buf; #ifdef _WIN32 - Slang::CharEncoding::UTF16->decode((const Byte*)wstr, (int)((wend - wstr) * sizeof(wchar_t)), buf); + Slang::CharEncoding::UTF16->decode( + (const Byte*)wstr, + (int)((wend - wstr) * sizeof(wchar_t)), + buf); #else - Slang::CharEncoding::UTF32->decode((const Byte*)wstr, (int)((wend - wstr) * sizeof(wchar_t)), buf); + Slang::CharEncoding::UTF32->decode( + (const Byte*)wstr, + (int)((wend - wstr) * sizeof(wchar_t)), + buf); #endif - return String(buf.begin(), buf.end()); - } + return String(buf.begin(), buf.end()); +} - String String::fromWChar(const wchar_t ch) - { - List<char> buf; +String String::fromWChar(const wchar_t ch) +{ + List<char> buf; #ifdef _WIN32 - Slang::CharEncoding::UTF16->decode((const Byte*)&ch, (int)(sizeof(wchar_t)), buf); + Slang::CharEncoding::UTF16->decode((const Byte*)&ch, (int)(sizeof(wchar_t)), buf); #else - Slang::CharEncoding::UTF32->decode((const Byte*)&ch, (int)(sizeof(wchar_t)), buf); + Slang::CharEncoding::UTF32->decode((const Byte*)&ch, (int)(sizeof(wchar_t)), buf); #endif - return String(buf.begin(), buf.end()); - } + return String(buf.begin(), buf.end()); +} + +/* static */ String String::fromUnicodePoint(Char32 codePoint) +{ + char buf[6]; + int len = Slang::encodeUnicodePointToUTF8(codePoint, buf); + return String(buf, buf + len); +} - /* static */String String::fromUnicodePoint(Char32 codePoint) +OSString String::toWString(Index* outLength) const +{ + if (!m_buffer) { - char buf[6]; - int len = Slang::encodeUnicodePointToUTF8(codePoint, buf); - return String(buf, buf + len); + return OSString(); } - - OSString String::toWString(Index* outLength) const + else { - if (!m_buffer) + List<Byte> buf; + switch (sizeof(wchar_t)) { - return OSString(); - } - else - { - List<Byte> buf; - switch(sizeof(wchar_t)) - { - case 2: - Slang::CharEncoding::UTF16->encode(getUnownedSlice(), buf); - break; + case 2: Slang::CharEncoding::UTF16->encode(getUnownedSlice(), buf); break; - case 4: - Slang::CharEncoding::UTF32->encode(getUnownedSlice(), buf); - break; + case 4: Slang::CharEncoding::UTF32->encode(getUnownedSlice(), buf); break; - default: - break; - } + default: break; + } - auto length = Index(buf.getCount() / sizeof(wchar_t)); - if (outLength) - *outLength = length; + auto length = Index(buf.getCount() / sizeof(wchar_t)); + if (outLength) + *outLength = length; - for(size_t ii = 0; ii < sizeof(wchar_t); ++ii) - buf.add(0); + for (size_t ii = 0; ii < sizeof(wchar_t); ++ii) + buf.add(0); - wchar_t* beginData = (wchar_t*)buf.getBuffer(); - wchar_t* endData = beginData + length; + wchar_t* beginData = (wchar_t*)buf.getBuffer(); + wchar_t* endData = beginData + length; - OSString ret; - ret.set(beginData, endData); - return ret; - } + OSString ret; + ret.set(beginData, endData); + return ret; } +} + +// - // +void String::ensureUniqueStorageWithCapacity(Index requiredCapacity) +{ + if (m_buffer && m_buffer->isUniquelyReferenced() && m_buffer->capacity >= requiredCapacity) + return; - void String::ensureUniqueStorageWithCapacity(Index requiredCapacity) + Index newCapacity = m_buffer ? 2 * m_buffer->capacity : 16; + if (newCapacity < requiredCapacity) { - if (m_buffer && m_buffer->isUniquelyReferenced() && m_buffer->capacity >= requiredCapacity) - return; + newCapacity = requiredCapacity; + } - Index newCapacity = m_buffer ? 2 * m_buffer->capacity : 16; - if (newCapacity < requiredCapacity) - { - newCapacity = requiredCapacity; - } + Index length = getLength(); + StringRepresentation* newRepresentation = + StringRepresentation::createWithCapacityAndLength(newCapacity, length); - Index length = getLength(); - StringRepresentation* newRepresentation = StringRepresentation::createWithCapacityAndLength(newCapacity, length); + if (m_buffer) + { + memcpy(newRepresentation->getData(), m_buffer->getData(), length + 1); + } - if (m_buffer) - { - memcpy(newRepresentation->getData(), m_buffer->getData(), length + 1); - } + m_buffer = newRepresentation; +} - m_buffer = newRepresentation; - } +char* String::prepareForAppend(Index count) +{ + auto oldLength = getLength(); + auto newLength = oldLength + count; + ensureUniqueStorageWithCapacity(newLength); + return getData() + oldLength; +} +void String::appendInPlace(const char* chars, Index count) +{ + SLANG_UNUSED(chars); - char* String::prepareForAppend(Index count) + if (count > 0) { + SLANG_ASSERT(m_buffer && m_buffer->isUniquelyReferenced()); + auto oldLength = getLength(); auto newLength = oldLength + count; - ensureUniqueStorageWithCapacity(newLength); - return getData() + oldLength; - } - void String::appendInPlace(const char* chars, Index count) - { - SLANG_UNUSED(chars); - - if (count > 0) - { - SLANG_ASSERT(m_buffer && m_buffer->isUniquelyReferenced()); - - auto oldLength = getLength(); - auto newLength = oldLength + count; - char* dst = m_buffer->getData(); + char* dst = m_buffer->getData(); - // Make sure the input buffer is the same one returned from prepareForAppend - SLANG_ASSERT(chars == dst + oldLength); - // It has to fit within the capacity - SLANG_ASSERT(newLength <= m_buffer->capacity); + // Make sure the input buffer is the same one returned from prepareForAppend + SLANG_ASSERT(chars == dst + oldLength); + // It has to fit within the capacity + SLANG_ASSERT(newLength <= m_buffer->capacity); - // We just need to modify the length - m_buffer->length = newLength; + // We just need to modify the length + m_buffer->length = newLength; - // And mark with a terminating 0 - dst[newLength] = 0; - } + // And mark with a terminating 0 + dst[newLength] = 0; } +} - void String::reduceLength(Index newLength) +void String::reduceLength(Index newLength) +{ + Index oldLength = getLength(); + SLANG_ASSERT(newLength <= oldLength); + if (oldLength == newLength) { - Index oldLength = getLength(); - SLANG_ASSERT(newLength <= oldLength); - if (oldLength == newLength) - { - return; - } + return; + } - // It must have a buffer, because only 0 length allows for nullptr - // and being 0 sized is already covered - SLANG_ASSERT(m_buffer); + // It must have a buffer, because only 0 length allows for nullptr + // and being 0 sized is already covered + SLANG_ASSERT(m_buffer); - if (m_buffer->isUniquelyReferenced()) + if (m_buffer->isUniquelyReferenced()) + { + m_buffer->length = newLength; + m_buffer->getData()[newLength] = 0; + } + else + { + // If 0 length is wanted we can just free + if (newLength == 0) { - m_buffer->length = newLength; - m_buffer->getData()[newLength] = 0; + m_buffer.setNull(); } else { - // If 0 length is wanted we can just free - if (newLength == 0) - { - m_buffer.setNull(); - } - else - { - // We need to make a new copy, that we will shrink + // We need to make a new copy, that we will shrink - // We'll just go with capacity enough for the new length - const Index newCapacity = newLength; - StringRepresentation* newRepresentation = StringRepresentation::createWithCapacityAndLength(newCapacity, newLength); + // We'll just go with capacity enough for the new length + const Index newCapacity = newLength; + StringRepresentation* newRepresentation = + StringRepresentation::createWithCapacityAndLength(newCapacity, newLength); - // Copy - char* dst = newRepresentation->getData(); - memcpy(dst, m_buffer->getData(), sizeof(char) * newLength); - // Zero terminate - dst[newLength] = 0; + // Copy + char* dst = newRepresentation->getData(); + memcpy(dst, m_buffer->getData(), sizeof(char) * newLength); + // Zero terminate + dst[newLength] = 0; - // Set the new rep - m_buffer = newRepresentation; - } + // Set the new rep + m_buffer = newRepresentation; } } +} - void String::append(char const* str, size_t len) - { - append(str, str + len); - } +void String::append(char const* str, size_t len) +{ + append(str, str + len); +} - void String::append(const char* textBegin, char const* textEnd) - { - auto oldLength = getLength(); - auto textLength = textEnd - textBegin; - if (textLength <= 0) - return; +void String::append(const char* textBegin, char const* textEnd) +{ + auto oldLength = getLength(); + auto textLength = textEnd - textBegin; + if (textLength <= 0) + return; - auto newLength = oldLength + textLength; + auto newLength = oldLength + textLength; - ensureUniqueStorageWithCapacity(newLength); + ensureUniqueStorageWithCapacity(newLength); - memcpy(getData() + oldLength, textBegin, textLength); - getData()[newLength] = 0; - m_buffer->length = newLength; - } + memcpy(getData() + oldLength, textBegin, textLength); + getData()[newLength] = 0; + m_buffer->length = newLength; +} - void String::append(char const* str) +void String::append(char const* str) +{ + if (str) { - if (str) - { - append(str, str + strlen(str)); - } + append(str, str + strlen(str)); } +} - void String::appendRepeatedChar(char chr, Index count) +void String::appendRepeatedChar(char chr, Index count) +{ + SLANG_ASSERT(count >= 0); + if (count > 0) { - SLANG_ASSERT(count >= 0); - if (count > 0) - { - char* chars = prepareForAppend(count); - // Set all space to repeated chr. - ::memset(chars, chr, sizeof(char) * count); - appendInPlace(chars, count); - } + char* chars = prepareForAppend(count); + // Set all space to repeated chr. + ::memset(chars, chr, sizeof(char) * count); + appendInPlace(chars, count); } +} - void String::appendChar(char c) - { - const auto oldLength = getLength(); - const auto newLength = oldLength + 1; +void String::appendChar(char c) +{ + const auto oldLength = getLength(); + const auto newLength = oldLength + 1; - ensureUniqueStorageWithCapacity(newLength); + ensureUniqueStorageWithCapacity(newLength); - // Since there must be space for at least one character, m_buffer cannot be nullptr - SLANG_ASSERT(m_buffer); - char* data = m_buffer->getData(); - data[oldLength] = c; - data[newLength] = 0; + // Since there must be space for at least one character, m_buffer cannot be nullptr + SLANG_ASSERT(m_buffer); + char* data = m_buffer->getData(); + data[oldLength] = c; + data[newLength] = 0; - m_buffer->length = newLength; - } + m_buffer->length = newLength; +} - void String::append(char chr) +void String::append(char chr) +{ + appendChar(chr); +} + +void String::append(String const& str) +{ + if (!m_buffer) { - appendChar(chr); + m_buffer = str.m_buffer; + return; } - void String::append(String const& str) - { - if (!m_buffer) - { - m_buffer = str.m_buffer; - return; - } + append(str.begin(), str.end()); +} - append(str.begin(), str.end()); - } +void String::append(StringSlice const& slice) +{ + append(slice.begin(), slice.end()); +} - void String::append(StringSlice const& slice) - { - append(slice.begin(), slice.end()); - } +void String::append(UnownedStringSlice const& slice) +{ + append(slice.begin(), slice.end()); +} - void String::append(UnownedStringSlice const& slice) +void String::append(int32_t value, int radix) +{ + enum { - append(slice.begin(), slice.end()); - } + kCount = 33 + }; + char* data = prepareForAppend(kCount); + const auto count = intToAscii(data, value, radix); + m_buffer->length += count; +} - void String::append(int32_t value, int radix) +void String::append(uint32_t value, int radix) +{ + enum { - enum { kCount = 33 }; - char* data = prepareForAppend(kCount); - const auto count = intToAscii(data, value, radix); - m_buffer->length += count; - } + kCount = 33 + }; + char* data = prepareForAppend(kCount); + const auto count = intToAscii(data, value, radix); + m_buffer->length += count; +} - void String::append(uint32_t value, int radix) +void String::append(int64_t value, int radix) +{ + enum { - enum { kCount = 33 }; - char* data = prepareForAppend(kCount); - const auto count = intToAscii(data, value, radix); - m_buffer->length += count; - } + kCount = 65 + }; + char* data = prepareForAppend(kCount); + auto count = intToAscii(data, value, radix); + m_buffer->length += count; +} - void String::append(int64_t value, int radix) +void String::append(uint64_t value, int radix) +{ + enum { - enum { kCount = 65 }; - char* data = prepareForAppend(kCount); - auto count = intToAscii(data, value, radix); - m_buffer->length += count; - } + kCount = 65 + }; + char* data = prepareForAppend(kCount); + auto count = intToAscii(data, value, radix); + m_buffer->length += count; +} - void String::append(uint64_t value, int radix) +void String::append(float val, const char* format) +{ + enum { - enum { kCount = 65 }; - char* data = prepareForAppend(kCount); - auto count = intToAscii(data, value, radix); - m_buffer->length += count; - } + kCount = 128 + }; + char* data = prepareForAppend(kCount); + sprintf_s(data, kCount, format, val); + m_buffer->length += strnlen_s(data, kCount); +} - void String::append(float val, const char* format) +void String::append(double val, const char* format) +{ + enum { - enum { kCount = 128 }; - char* data = prepareForAppend(kCount); - sprintf_s(data, kCount, format, val); - m_buffer->length += strnlen_s(data, kCount); - } + kCount = 128 + }; + char* data = prepareForAppend(kCount); + sprintf_s(data, kCount, format, val); + m_buffer->length += strnlen_s(data, kCount); +} + +void String::append(StableHashCode32 value) +{ + const Index digits = 8; + // + null terminator + char* data = prepareForAppend(digits + 1); + auto count = intToAscii(data, value.hash, 16, digits); + m_buffer->length += count; +} - void String::append(double val, const char* format) +void String::append(StableHashCode64 value) +{ + const Index digits = 16; + // + null terminator + char* data = prepareForAppend(digits + 1); + auto count = intToAscii(data, value.hash, 16, digits); + m_buffer->length += count; +} + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UnownedStringSlice !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Index UnownedStringSlice::indexOf(char c) const +{ + const Index size = Index(m_end - m_begin); + for (Index i = 0; i < size; ++i) { - enum { kCount = 128 }; - char* data = prepareForAppend(kCount); - sprintf_s(data, kCount, format, val); - m_buffer->length += strnlen_s(data, kCount); + if (m_begin[i] == c) + { + return i; + } } + return -1; +} - void String::append(StableHashCode32 value) +Index UnownedStringSlice::indexOf(const UnownedStringSlice& in) const +{ + const Index len = getLength(); + const Index inLen = in.getLength(); + if (inLen > len) { - const Index digits = 8; - // + null terminator - char* data = prepareForAppend(digits + 1); - auto count = intToAscii(data, value.hash, 16, digits); - m_buffer->length += count; + return -1; } - void String::append(StableHashCode64 value) + const char* inChars = in.m_begin; + switch (inLen) { - const Index digits = 16; - // + null terminator - char* data = prepareForAppend(digits + 1); - auto count = intToAscii(data, value.hash, 16, digits); - m_buffer->length += count; + case 0: return 0; + case 1: return indexOf(inChars[0]); + default: break; } - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UnownedStringSlice !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + const char* chars = m_begin; + const char firstChar = inChars[0]; - Index UnownedStringSlice::indexOf(char c) const + for (Int i = 0; i <= len - inLen; ++i) { - const Index size = Index(m_end - m_begin); - for (Index i = 0; i < size; ++i) + if (chars[i] == firstChar && in == UnownedStringSlice(chars + i, inLen)) { - if (m_begin[i] == c) - { - return i; - } + return i; } - return -1; } - Index UnownedStringSlice::indexOf(const UnownedStringSlice& in) const - { - const Index len = getLength(); - const Index inLen = in.getLength(); - if (inLen > len) - { - return -1; - } + return -1; +} - const char* inChars = in.m_begin; - switch (inLen) - { - case 0: return 0; - case 1: return indexOf(inChars[0]); - default: break; - } +UnownedStringSlice UnownedStringSlice::subString(Index idx, Index len) const +{ + const Index totalLen = getLength(); + SLANG_ASSERT(idx >= 0 && len >= 0 && idx <= totalLen); - const char* chars = m_begin; - const char firstChar = inChars[0]; + // If too large, we truncate + len = (idx + len > totalLen) ? (totalLen - idx) : len; - for (Int i = 0; i <= len - inLen; ++i) - { - if (chars[i] == firstChar && in == UnownedStringSlice(chars + i, inLen)) - { - return i; - } - } + // Return the substring + return UnownedStringSlice(m_begin + idx, m_begin + idx + len); +} - return -1; - } +bool UnownedStringSlice::operator==(ThisType const& other) const +{ + // Note that memcmp is undefined when passed in null ptrs, so if we want to handle + // we need to cover that case. + // Can only be nullptr if size is 0. + auto thisSize = getLength(); + auto otherSize = other.getLength(); - UnownedStringSlice UnownedStringSlice::subString(Index idx, Index len) const + if (thisSize != otherSize) { - const Index totalLen = getLength(); - SLANG_ASSERT(idx >= 0 && len >= 0 && idx <= totalLen); - - // If too large, we truncate - len = (idx + len > totalLen) ? (totalLen - idx) : len; - - // Return the substring - return UnownedStringSlice(m_begin + idx, m_begin + idx + len); + return false; } - bool UnownedStringSlice::operator==(ThisType const& other) const + const char* const thisChars = begin(); + const char* const otherChars = other.begin(); + if (thisChars == otherChars || thisSize == 0) { - // Note that memcmp is undefined when passed in null ptrs, so if we want to handle - // we need to cover that case. - // Can only be nullptr if size is 0. - auto thisSize = getLength(); - auto otherSize = other.getLength(); - - if (thisSize != otherSize) - { - return false; - } - - const char*const thisChars = begin(); - const char*const otherChars = other.begin(); - if (thisChars == otherChars || thisSize == 0) - { - return true; - } - SLANG_ASSERT(thisChars && otherChars); - return memcmp(thisChars, otherChars, thisSize) == 0; + return true; } + SLANG_ASSERT(thisChars && otherChars); + return memcmp(thisChars, otherChars, thisSize) == 0; +} - bool UnownedStringSlice::caseInsensitiveEquals(const ThisType& rhs) const +bool UnownedStringSlice::caseInsensitiveEquals(const ThisType& rhs) const +{ + const auto length = getLength(); + if (length != rhs.getLength()) { - const auto length = getLength(); - if (length != rhs.getLength()) - { - return false; - } + return false; + } - const char* a = m_begin; - const char* b = rhs.m_begin; + const char* a = m_begin; + const char* b = rhs.m_begin; - // Assuming this is a faster test - if (memcmp(a, b, length) != 0) + // Assuming this is a faster test + if (memcmp(a, b, length) != 0) + { + // They aren't identical so compare character by character + for (Index i = 0; i < length; ++i) { - // They aren't identical so compare character by character - for (Index i = 0; i < length; ++i) + if (CharUtil::toLower(a[i]) != CharUtil::toLower(b[i])) { - if (CharUtil::toLower(a[i]) != CharUtil::toLower(b[i])) - { - return false; - } + return false; } } - - return true; } + + return true; } +} // namespace Slang -std::ostream& operator<< (std::ostream& stream, const Slang::String& s) +std::ostream& operator<<(std::ostream& stream, const Slang::String& s) { stream << s.getBuffer(); return stream; |
