summaryrefslogtreecommitdiff
path: root/source/core/slang-string.h
diff options
context:
space:
mode:
Diffstat (limited to 'source/core/slang-string.h')
-rw-r--r--source/core/slang-string.h1514
1 files changed, 697 insertions, 817 deletions
diff --git a/source/core/slang-string.h b/source/core/slang-string.h
index 6c0dec420..24b119383 100644
--- a/source/core/slang-string.h
+++ b/source/core/slang-string.h
@@ -1,989 +1,872 @@
#ifndef SLANG_CORE_STRING_H
#define SLANG_CORE_STRING_H
-#include <string.h>
-#include <cstdlib>
-#include <stdio.h>
-#include <iostream>
-
-#include "slang-smart-pointer.h"
#include "slang-common.h"
#include "slang-hash.h"
#include "slang-secure-crt.h"
+#include "slang-smart-pointer.h"
#include "slang-stable-hash.h"
+#include <cstdlib>
+#include <iostream>
#include <new>
+#include <stdio.h>
+#include <string.h>
#include <type_traits>
namespace Slang
{
- class _EndLine
- {};
- extern _EndLine EndLine;
+class _EndLine
+{
+};
+extern _EndLine EndLine;
- // in-place reversion, works only for ascii string
- inline void reverseInplaceAscii(char* buffer, int length)
+// in-place reversion, works only for ascii string
+inline void reverseInplaceAscii(char* buffer, int length)
+{
+ int i, j;
+ char c;
+ for (i = 0, j = length - 1; i < j; i++, j--)
{
- int i, j;
- char c;
- for (i = 0, j = length - 1; i<j; i++, j--)
- {
- c = buffer[i];
- buffer[i] = buffer[j];
- buffer[j] = c;
- }
+ c = buffer[i];
+ buffer[i] = buffer[j];
+ buffer[j] = c;
}
- template<typename IntType>
- inline int intToAscii(char* buffer, IntType val, int radix, int padTo = 0)
+}
+template<typename IntType>
+inline int intToAscii(char* buffer, IntType val, int radix, int padTo = 0)
+{
+ static_assert(std::is_integral_v<IntType>);
+
+ int i = 0;
+ IntType sign;
+
+ sign = val;
+ if (sign < 0)
{
- static_assert(std::is_integral_v<IntType>);
+ val = (IntType)(0 - val);
+ }
- int i = 0;
- IntType sign;
-
- sign = val;
- if (sign < 0)
- {
- val = (IntType)(0 - val);
- }
+ do
+ {
+ int digit = (val % radix);
+ if (digit <= 9)
+ buffer[i++] = (char)(digit + '0');
+ else
+ buffer[i++] = (char)(digit - 10 + 'A');
+ } while ((val /= radix) > 0);
- do
- {
- int digit = (val % radix);
- if (digit <= 9)
- buffer[i++] = (char)(digit + '0');
- else
- buffer[i++] = (char)(digit - 10 + 'A');
- } while ((val /= radix) > 0);
+ SLANG_ASSERT(i >= 0);
+ while (i < padTo)
+ buffer[i++] = '0';
- SLANG_ASSERT(i >= 0);
- while(i < padTo)
- buffer[i++] = '0';
+ if (sign < 0)
+ buffer[i++] = '-';
- if (sign < 0)
- buffer[i++] = '-';
+ // Put in normal character order
+ reverseInplaceAscii(buffer, i);
- // Put in normal character order
- reverseInplaceAscii(buffer, i);
+ buffer[i] = '\0';
+ return i;
+}
- buffer[i] = '\0';
- return i;
- }
+SLANG_FORCE_INLINE bool isUtf8LeadingByte(char ch)
+{
+ return (((unsigned char)ch) & 0xC0) == 0xC0;
+}
+
+SLANG_FORCE_INLINE bool isUtf8ContinuationByte(char ch)
+{
+ return (((unsigned char)ch) & 0xC0) == 0x80;
+}
- SLANG_FORCE_INLINE bool isUtf8LeadingByte(char ch)
+/* A string slice that doesn't own the contained characters.
+It is the responsibility of code using the type to keep the memory backing
+the slice in scope.
+A slice is generally *not* zero terminated. */
+struct SLANG_RT_API UnownedStringSlice
+{
+public:
+ typedef UnownedStringSlice ThisType;
+
+ // Type to indicate that a ctor is with a length to disabmiguate 0/nullptr
+ // causing ambiguity.
+ struct WithLength
{
- return (((unsigned char)ch) & 0xC0) == 0xC0;
- }
+ };
- SLANG_FORCE_INLINE bool isUtf8ContinuationByte(char ch)
+ UnownedStringSlice()
+ : m_begin(nullptr), m_end(nullptr)
{
- return (((unsigned char)ch) & 0xC0) == 0x80;
}
- /* A string slice that doesn't own the contained characters.
- It is the responsibility of code using the type to keep the memory backing
- the slice in scope.
- A slice is generally *not* zero terminated. */
- struct SLANG_RT_API UnownedStringSlice
+ explicit UnownedStringSlice(char const* a)
+ : m_begin(a), m_end(a ? a + strlen(a) : nullptr)
{
- public:
- typedef UnownedStringSlice ThisType;
-
- // Type to indicate that a ctor is with a length to disabmiguate 0/nullptr
- // causing ambiguity.
- struct WithLength {};
-
- UnownedStringSlice()
- : m_begin(nullptr)
- , m_end(nullptr)
- {}
-
- explicit UnownedStringSlice(char const* a) :
- m_begin(a),
- m_end(a ? a + strlen(a) : nullptr)
- {}
- UnownedStringSlice(char const* b, char const* e)
- : m_begin(b)
- , m_end(e)
- {}
- UnownedStringSlice(char const* b, size_t len)
- : m_begin(b)
- , m_end(b + len)
- {}
- UnownedStringSlice(WithLength, char const* b, size_t len)
- : m_begin(b)
- , m_end(b + len)
- {}
+ }
+ UnownedStringSlice(char const* b, char const* e)
+ : m_begin(b), m_end(e)
+ {
+ }
+ UnownedStringSlice(char const* b, size_t len)
+ : m_begin(b), m_end(b + len)
+ {
+ }
+ UnownedStringSlice(WithLength, char const* b, size_t len)
+ : m_begin(b), m_end(b + len)
+ {
+ }
- SLANG_FORCE_INLINE char const* begin() const { return m_begin; }
+ SLANG_FORCE_INLINE char const* begin() const { return m_begin; }
- SLANG_FORCE_INLINE char const* end() const { return m_end; }
+ SLANG_FORCE_INLINE char const* end() const { return m_end; }
- /// True if slice is strictly contained in memory.
- bool isMemoryContained(const UnownedStringSlice& slice) const
- {
- return slice.m_begin >= m_begin && slice.m_end <= m_end;
- }
- bool isMemoryContained(const char* pos) const
- {
- return pos >= m_begin && pos <= m_end;
- }
+ /// True if slice is strictly contained in memory.
+ bool isMemoryContained(const UnownedStringSlice& slice) const
+ {
+ return slice.m_begin >= m_begin && slice.m_end <= m_end;
+ }
+ bool isMemoryContained(const char* pos) const { return pos >= m_begin && pos <= m_end; }
- /// Get the length in *bytes*
- Count getLength() const { return Index(m_end - m_begin); }
+ /// Get the length in *bytes*
+ Count getLength() const { return Index(m_end - m_begin); }
- /// Finds first index of char 'c'. If not found returns -1.
- Index indexOf(char c) const;
- /// Find first index of slice. If not found returns -1
- Index indexOf(const UnownedStringSlice& slice) const;
+ /// Finds first index of char 'c'. If not found returns -1.
+ Index indexOf(char c) const;
+ /// Find first index of slice. If not found returns -1
+ Index indexOf(const UnownedStringSlice& slice) const;
- /// Returns a substring. idx is the start index, and len
- /// is the amount of characters.
- /// The returned length might be truncated, if len extends beyond slice.
- UnownedStringSlice subString(Index idx, Index len) const;
+ /// Returns a substring. idx is the start index, and len
+ /// is the amount of characters.
+ /// The returned length might be truncated, if len extends beyond slice.
+ UnownedStringSlice subString(Index idx, Index len) const;
- /// Return a head of the slice - everything up to the index
- SLANG_FORCE_INLINE UnownedStringSlice head(Index idx) const { SLANG_ASSERT(idx >= 0 && idx <= getLength()); return UnownedStringSlice(m_begin, idx); }
- /// Return a tail of the slice - everything from the index to the end of the slice
- SLANG_FORCE_INLINE UnownedStringSlice tail(Index idx) const { SLANG_ASSERT(idx >= 0 && idx <= getLength()); return UnownedStringSlice(m_begin + idx, m_end); }
+ /// Return a head of the slice - everything up to the index
+ SLANG_FORCE_INLINE UnownedStringSlice head(Index idx) const
+ {
+ SLANG_ASSERT(idx >= 0 && idx <= getLength());
+ return UnownedStringSlice(m_begin, idx);
+ }
+ /// Return a tail of the slice - everything from the index to the end of the slice
+ SLANG_FORCE_INLINE UnownedStringSlice tail(Index idx) const
+ {
+ SLANG_ASSERT(idx >= 0 && idx <= getLength());
+ return UnownedStringSlice(m_begin + idx, m_end);
+ }
- /// True if rhs and this are equal without having to take into account case
- /// Note 'case' here is *not* locale specific - it is only A-Z and a-z
- bool caseInsensitiveEquals(const ThisType& rhs) const;
+ /// True if rhs and this are equal without having to take into account case
+ /// Note 'case' here is *not* locale specific - it is only A-Z and a-z
+ bool caseInsensitiveEquals(const ThisType& rhs) const;
- Index lastIndexOf(char c) const
+ Index lastIndexOf(char c) const
+ {
+ const Index size = Index(m_end - m_begin);
+ for (Index i = size - 1; i >= 0; --i)
{
- const Index size = Index(m_end - m_begin);
- for (Index i = size - 1; i >= 0; --i)
+ if (m_begin[i] == c)
{
- if (m_begin[i] == c)
- {
- return i;
- }
+ return i;
}
- return -1;
}
+ return -1;
+ }
- const char& operator[](Index i) const
- {
- assert(i >= 0 && i < Index(m_end - m_begin));
- return m_begin[i];
- }
+ const char& operator[](Index i) const
+ {
+ assert(i >= 0 && i < Index(m_end - m_begin));
+ return m_begin[i];
+ }
- bool operator==(ThisType const& other) const;
- bool operator!=(UnownedStringSlice const& other) const { return !(*this == other); }
+ bool operator==(ThisType const& other) const;
+ bool operator!=(UnownedStringSlice const& other) const { return !(*this == other); }
- bool operator==(char const* str) const { return (*this) == UnownedStringSlice(str); }
- bool operator!=(char const* str) const { return !(*this == str); }
+ bool operator==(char const* str) const { return (*this) == UnownedStringSlice(str); }
+ bool operator!=(char const* str) const { return !(*this == str); }
- /// True if contents is a single char of c
- SLANG_FORCE_INLINE bool isChar(char c) const { return getLength() == 1 && m_begin[0] == c; }
+ /// True if contents is a single char of c
+ SLANG_FORCE_INLINE bool isChar(char c) const { return getLength() == 1 && m_begin[0] == c; }
- bool startsWithCaseInsensitive(UnownedStringSlice const& other) const;
- bool startsWith(UnownedStringSlice const& other) const;
- bool startsWith(char const* str) const;
+ bool startsWithCaseInsensitive(UnownedStringSlice const& other) const;
+ bool startsWith(UnownedStringSlice const& other) const;
+ bool startsWith(char const* str) const;
- bool endsWithCaseInsensitive(UnownedStringSlice const& other) const;
- bool endsWithCaseInsensitive(char const* str) const;
+ bool endsWithCaseInsensitive(UnownedStringSlice const& other) const;
+ bool endsWithCaseInsensitive(char const* str) const;
- bool endsWith(UnownedStringSlice const& other) const;
- bool endsWith(char const* str) const;
+ bool endsWith(UnownedStringSlice const& other) const;
+ bool endsWith(char const* str) const;
- /// Trims any horizontal whitespace from the start and end and returns as a substring
- UnownedStringSlice trim() const;
- /// Trims any 'c' from the start or the end, and returns as a substring
- UnownedStringSlice trim(char c) const;
+ /// Trims any horizontal whitespace from the start and end and returns as a substring
+ UnownedStringSlice trim() const;
+ /// Trims any 'c' from the start or the end, and returns as a substring
+ UnownedStringSlice trim(char c) const;
- /// Trims any horizonatl whitespace from start and returns as a substring
- UnownedStringSlice trimStart() const;
+ /// Trims any horizonatl whitespace from start and returns as a substring
+ UnownedStringSlice trimStart() const;
- static constexpr bool kHasUniformHash = true;
- HashCode64 getHashCode() const
- {
- return Slang::getHashCode(m_begin, size_t(m_end - m_begin));
- }
+ static constexpr bool kHasUniformHash = true;
+ HashCode64 getHashCode() const { return Slang::getHashCode(m_begin, size_t(m_end - m_begin)); }
- template <size_t SIZE>
- SLANG_FORCE_INLINE static UnownedStringSlice fromLiteral(const char (&in)[SIZE]) { return UnownedStringSlice(in, SIZE - 1); }
+ template<size_t SIZE>
+ SLANG_FORCE_INLINE static UnownedStringSlice fromLiteral(const char (&in)[SIZE])
+ {
+ return UnownedStringSlice(in, SIZE - 1);
+ }
- protected:
+protected:
+ char const* m_begin;
+ char const* m_end;
+};
- char const* m_begin;
- char const* m_end;
- };
+// A more convenient way to make slices from *string literals*
+template<size_t SIZE>
+SLANG_FORCE_INLINE UnownedStringSlice toSlice(const char (&in)[SIZE])
+{
+ return UnownedStringSlice(in, SIZE - 1);
+}
- // A more convenient way to make slices from *string literals*
- template <size_t SIZE>
- SLANG_FORCE_INLINE UnownedStringSlice toSlice(const char (&in)[SIZE]) { return UnownedStringSlice(in, SIZE - 1); }
-
- /// Same as UnownedStringSlice, but must be zero terminated.
- /// Zero termination is *not* included in the length.
- struct SLANG_RT_API UnownedTerminatedStringSlice : public UnownedStringSlice
- {
- public:
- typedef UnownedStringSlice Super;
- typedef UnownedTerminatedStringSlice ThisType;
-
- /// We can turn into a regular zero terminated string
- SLANG_FORCE_INLINE operator const char*() const { return m_begin; }
-
- /// Exists to match the equivalent function in String.
- SLANG_FORCE_INLINE char const* getBuffer() const { return m_begin; }
-
- /// Construct from a literal directly.
- template <size_t SIZE>
- SLANG_FORCE_INLINE static ThisType fromLiteral(const char(&in)[SIZE]) { return ThisType(in, SIZE - 1); }
-
- /// Default constructor
- UnownedTerminatedStringSlice():Super(Super::WithLength(), "", 0) {}
-
- /// Note, b cannot be null because if it were then the string would not be null terminated
- UnownedTerminatedStringSlice(char const* b)
- : Super(b, b + strlen(b))
- {}
- UnownedTerminatedStringSlice(char const* b, size_t len)
- : Super(b, len)
- {
- // b must be valid and it must be null terminated
- SLANG_ASSERT(b && b[len] == 0);
- }
- };
+/// Same as UnownedStringSlice, but must be zero terminated.
+/// Zero termination is *not* included in the length.
+struct SLANG_RT_API UnownedTerminatedStringSlice : public UnownedStringSlice
+{
+public:
+ typedef UnownedStringSlice Super;
+ typedef UnownedTerminatedStringSlice ThisType;
+
+ /// We can turn into a regular zero terminated string
+ SLANG_FORCE_INLINE operator const char*() const { return m_begin; }
- // A more convenient way to make terminated slices from *string literals*
- template <size_t SIZE>
- SLANG_FORCE_INLINE UnownedTerminatedStringSlice toTerminatedSlice(const char(&in)[SIZE]) { return UnownedTerminatedStringSlice(in, SIZE - 1); }
+ /// Exists to match the equivalent function in String.
+ SLANG_FORCE_INLINE char const* getBuffer() const { return m_begin; }
- // A `StringRepresentation` provides the backing storage for
- // all reference-counted string-related types.
- class SLANG_RT_API StringRepresentation : public RefObject
+ /// Construct from a literal directly.
+ template<size_t SIZE>
+ SLANG_FORCE_INLINE static ThisType fromLiteral(const char (&in)[SIZE])
{
- public:
- Index length;
- Index capacity;
+ return ThisType(in, SIZE - 1);
+ }
- SLANG_FORCE_INLINE Index getLength() const
- {
- return length;
- }
+ /// Default constructor
+ UnownedTerminatedStringSlice()
+ : Super(Super::WithLength(), "", 0)
+ {
+ }
- SLANG_FORCE_INLINE char* getData()
- {
- return (char*) (this + 1);
- }
- SLANG_FORCE_INLINE const char* getData() const
- {
- return (const char*)(this + 1);
- }
+ /// Note, b cannot be null because if it were then the string would not be null terminated
+ UnownedTerminatedStringSlice(char const* b)
+ : Super(b, b + strlen(b))
+ {
+ }
+ UnownedTerminatedStringSlice(char const* b, size_t len)
+ : Super(b, len)
+ {
+ // b must be valid and it must be null terminated
+ SLANG_ASSERT(b && b[len] == 0);
+ }
+};
- /// Set the contents to be the slice. Must be enough capacity to hold the slice.
- void setContents(const UnownedStringSlice& slice);
+// A more convenient way to make terminated slices from *string literals*
+template<size_t SIZE>
+SLANG_FORCE_INLINE UnownedTerminatedStringSlice toTerminatedSlice(const char (&in)[SIZE])
+{
+ return UnownedTerminatedStringSlice(in, SIZE - 1);
+}
- static const char* getData(const StringRepresentation* stringRep)
- {
- return stringRep ? stringRep->getData() : "";
- }
+// A `StringRepresentation` provides the backing storage for
+// all reference-counted string-related types.
+class SLANG_RT_API StringRepresentation : public RefObject
+{
+public:
+ Index length;
+ Index capacity;
- static UnownedStringSlice asSlice(const StringRepresentation* rep)
- {
- return rep ? UnownedStringSlice(rep->getData(), rep->getLength()) : UnownedStringSlice();
- }
+ SLANG_FORCE_INLINE Index getLength() const { return length; }
- static bool equal(const StringRepresentation* a, const StringRepresentation* b)
- {
- return (a == b) || asSlice(a) == asSlice(b);
- }
+ SLANG_FORCE_INLINE char* getData() { return (char*)(this + 1); }
+ SLANG_FORCE_INLINE const char* getData() const { return (const char*)(this + 1); }
- static StringRepresentation* createWithCapacityAndLength(Index capacity, Index length)
- {
- SLANG_ASSERT(capacity >= length);
- void* allocation = operator new(sizeof(StringRepresentation) + capacity + 1);
- StringRepresentation* obj = new(allocation) StringRepresentation();
- obj->capacity = capacity;
- obj->length = length;
- obj->getData()[length] = 0;
- return obj;
- }
+ /// Set the contents to be the slice. Must be enough capacity to hold the slice.
+ void setContents(const UnownedStringSlice& slice);
- static StringRepresentation* createWithCapacity(Index capacity)
- {
- return createWithCapacityAndLength(capacity, 0);
- }
+ static const char* getData(const StringRepresentation* stringRep)
+ {
+ return stringRep ? stringRep->getData() : "";
+ }
- static StringRepresentation* createWithLength(Index length)
- {
- return createWithCapacityAndLength(length, length);
- }
+ static UnownedStringSlice asSlice(const StringRepresentation* rep)
+ {
+ return rep ? UnownedStringSlice(rep->getData(), rep->getLength()) : UnownedStringSlice();
+ }
- /// Create a representation from the slice. If slice is empty will return nullptr.
- static StringRepresentation* create(const UnownedStringSlice& slice);
- /// Same as create, but representation will have refcount of 1 (if not nullptr)
- static StringRepresentation* createWithReference(const UnownedStringSlice& slice);
+ static bool equal(const StringRepresentation* a, const StringRepresentation* b)
+ {
+ return (a == b) || asSlice(a) == asSlice(b);
+ }
- StringRepresentation* cloneWithCapacity(Index newCapacity)
- {
- StringRepresentation* newObj = createWithCapacityAndLength(newCapacity, length);
- memcpy(getData(), newObj->getData(), length + 1);
- return newObj;
- }
+ static StringRepresentation* createWithCapacityAndLength(Index capacity, Index length)
+ {
+ SLANG_ASSERT(capacity >= length);
+ void* allocation = operator new(sizeof(StringRepresentation) + capacity + 1);
+ StringRepresentation* obj = new (allocation) StringRepresentation();
+ obj->capacity = capacity;
+ obj->length = length;
+ obj->getData()[length] = 0;
+ return obj;
+ }
- StringRepresentation* clone()
- {
- return cloneWithCapacity(length);
- }
+ static StringRepresentation* createWithCapacity(Index capacity)
+ {
+ return createWithCapacityAndLength(capacity, 0);
+ }
- StringRepresentation* ensureCapacity(Index required)
- {
- if (capacity >= required) return this;
+ static StringRepresentation* createWithLength(Index length)
+ {
+ return createWithCapacityAndLength(length, length);
+ }
- Index newCapacity = capacity;
- if (!newCapacity) newCapacity = 16; // TODO: figure out good value for minimum capacity
+ /// Create a representation from the slice. If slice is empty will return nullptr.
+ static StringRepresentation* create(const UnownedStringSlice& slice);
+ /// Same as create, but representation will have refcount of 1 (if not nullptr)
+ static StringRepresentation* createWithReference(const UnownedStringSlice& slice);
- while (newCapacity < required)
- {
- newCapacity = 2 * newCapacity;
- }
+ StringRepresentation* cloneWithCapacity(Index newCapacity)
+ {
+ StringRepresentation* newObj = createWithCapacityAndLength(newCapacity, length);
+ memcpy(getData(), newObj->getData(), length + 1);
+ return newObj;
+ }
- return cloneWithCapacity(newCapacity);
- }
+ StringRepresentation* clone() { return cloneWithCapacity(length); }
+
+ StringRepresentation* ensureCapacity(Index required)
+ {
+ if (capacity >= required)
+ return this;
- /// Overload delete to silence ASAN new-delete-type-mismatch errors.
- /// These occur because the allocation size of StringRepresentation
- /// does not match deallocation size (due variable sized string payload).
- void operator delete(void* p)
+ Index newCapacity = capacity;
+ if (!newCapacity)
+ newCapacity = 16; // TODO: figure out good value for minimum capacity
+
+ while (newCapacity < required)
{
- StringRepresentation* str = (StringRepresentation*) p;
- ::operator delete(str);
- }
- };
+ newCapacity = 2 * newCapacity;
+ }
- class String;
+ return cloneWithCapacity(newCapacity);
+ }
- struct SLANG_RT_API StringSlice
+ /// Overload delete to silence ASAN new-delete-type-mismatch errors.
+ /// These occur because the allocation size of StringRepresentation
+ /// does not match deallocation size (due variable sized string payload).
+ void operator delete(void* p)
{
- public:
- StringSlice();
+ StringRepresentation* str = (StringRepresentation*)p;
+ ::operator delete(str);
+ }
+};
- StringSlice(String const& str);
+class String;
- StringSlice(String const& str, UInt beginIndex, UInt endIndex);
+struct SLANG_RT_API StringSlice
+{
+public:
+ StringSlice();
- UInt getLength() const
- {
- return endIndex - beginIndex;
- }
+ StringSlice(String const& str);
- char const* begin() const
- {
- return representation ? representation->getData() + beginIndex : "";
- }
+ StringSlice(String const& str, UInt beginIndex, UInt endIndex);
- char const* end() const
- {
- return begin() + getLength();
- }
+ UInt getLength() const { return endIndex - beginIndex; }
- private:
- RefPtr<StringRepresentation> representation;
- UInt beginIndex;
- UInt endIndex;
+ char const* begin() const
+ {
+ return representation ? representation->getData() + beginIndex : "";
+ }
- friend class String;
+ char const* end() const { return begin() + getLength(); }
- StringSlice(RefPtr<StringRepresentation> const& representation, UInt beginIndex, UInt endIndex)
- : representation(representation)
- , beginIndex(beginIndex)
- , endIndex(endIndex)
- {}
- };
+private:
+ RefPtr<StringRepresentation> representation;
+ UInt beginIndex;
+ UInt endIndex;
- /// String as expected by underlying platform APIs
- class SLANG_RT_API OSString
- {
- public:
- /// Default
- OSString();
- /// NOTE! This assumes that begin is a new wchar_t[] buffer, and it will
- /// now be owned by the OSString
- OSString(wchar_t* begin, wchar_t* end);
- /// Move Ctor
- OSString(OSString&& rhs):
- m_begin(rhs.m_begin),
- m_end(rhs.m_end)
- {
- rhs.m_begin = nullptr;
- rhs.m_end = nullptr;
- }
- // Copy Ctor
- OSString(const OSString& rhs) :
- m_begin(nullptr),
- m_end(nullptr)
- {
- set(rhs.m_begin, rhs.m_end);
- }
+ friend class String;
- /// =
- void operator=(const OSString& rhs) { set(rhs.m_begin, rhs.m_end); }
- void operator=(OSString&& rhs)
- {
- auto begin = m_begin;
- auto end = m_end;
- m_begin = rhs.m_begin;
- m_end = rhs.m_end;
- rhs.m_begin = begin;
- rhs.m_end = end;
- }
+ StringSlice(RefPtr<StringRepresentation> const& representation, UInt beginIndex, UInt endIndex)
+ : representation(representation), beginIndex(beginIndex), endIndex(endIndex)
+ {
+ }
+};
- ~OSString() { _releaseBuffer(); }
+/// String as expected by underlying platform APIs
+class SLANG_RT_API OSString
+{
+public:
+ /// Default
+ OSString();
+ /// NOTE! This assumes that begin is a new wchar_t[] buffer, and it will
+ /// now be owned by the OSString
+ OSString(wchar_t* begin, wchar_t* end);
+ /// Move Ctor
+ OSString(OSString&& rhs)
+ : m_begin(rhs.m_begin), m_end(rhs.m_end)
+ {
+ rhs.m_begin = nullptr;
+ rhs.m_end = nullptr;
+ }
+ // Copy Ctor
+ OSString(const OSString& rhs)
+ : m_begin(nullptr), m_end(nullptr)
+ {
+ set(rhs.m_begin, rhs.m_end);
+ }
- size_t getLength() const { return (m_end - m_begin); }
- void set(const wchar_t* begin, const wchar_t* end);
+ /// =
+ void operator=(const OSString& rhs) { set(rhs.m_begin, rhs.m_end); }
+ void operator=(OSString&& rhs)
+ {
+ auto begin = m_begin;
+ auto end = m_end;
+ m_begin = rhs.m_begin;
+ m_end = rhs.m_end;
+ rhs.m_begin = begin;
+ rhs.m_end = end;
+ }
- operator wchar_t const*() const
- {
- return begin();
- }
+ ~OSString() { _releaseBuffer(); }
- wchar_t const* begin() const;
- wchar_t const* end() const;
+ size_t getLength() const { return (m_end - m_begin); }
+ void set(const wchar_t* begin, const wchar_t* end);
- private:
+ operator wchar_t const*() const { return begin(); }
- void _releaseBuffer();
+ wchar_t const* begin() const;
+ wchar_t const* end() const;
- wchar_t* m_begin; ///< First character. This is a new wchar_t[] buffer
- wchar_t* m_end; ///< Points to terminating 0
- };
+private:
+ void _releaseBuffer();
- /*!
- @brief Represents a UTF-8 encoded string.
- */
+ wchar_t* m_begin; ///< First character. This is a new wchar_t[] buffer
+ wchar_t* m_end; ///< Points to terminating 0
+};
- class SLANG_RT_API String
- {
- friend struct StringSlice;
- friend class StringBuilder;
- private:
+/*!
+@brief Represents a UTF-8 encoded string.
+*/
+class SLANG_RT_API String
+{
+ friend struct StringSlice;
+ friend class StringBuilder;
- char* getData() const
- {
- return m_buffer ? m_buffer->getData() : (char*)"";
- }
+private:
+ char* getData() const { return m_buffer ? m_buffer->getData() : (char*)""; }
-
- void ensureUniqueStorageWithCapacity(Index capacity);
-
- RefPtr<StringRepresentation> m_buffer;
- public:
+ void ensureUniqueStorageWithCapacity(Index capacity);
- explicit String(StringRepresentation* buffer)
- : m_buffer(buffer)
- {}
+ RefPtr<StringRepresentation> m_buffer;
- static String fromWString(const wchar_t* wstr);
- static String fromWString(const wchar_t* wstr, const wchar_t* wend);
- static String fromWChar(const wchar_t ch);
- static String fromUnicodePoint(Char32 codePoint);
+public:
+ explicit String(StringRepresentation* buffer)
+ : m_buffer(buffer)
+ {
+ }
- String()
- {
- }
+ static String fromWString(const wchar_t* wstr);
+ static String fromWString(const wchar_t* wstr, const wchar_t* wend);
+ static String fromWChar(const wchar_t ch);
+ static String fromUnicodePoint(Char32 codePoint);
- /// Returns a buffer which can hold at least count chars
- char* prepareForAppend(Index count);
- /// Append data written to buffer output via 'prepareForAppend' directly written 'inplace'
- void appendInPlace(const char* chars, Index count);
+ String() {}
- /// Get the internal string represenation
- SLANG_FORCE_INLINE StringRepresentation* getStringRepresentation() const { return m_buffer; }
+ /// Returns a buffer which can hold at least count chars
+ char* prepareForAppend(Index count);
+ /// Append data written to buffer output via 'prepareForAppend' directly written 'inplace'
+ void appendInPlace(const char* chars, Index count);
- /// Detach the representation (will leave string as empty). Rep ref count will remain unchanged.
- SLANG_FORCE_INLINE StringRepresentation* detachStringRepresentation() { return m_buffer.detach(); }
+ /// Get the internal string represenation
+ SLANG_FORCE_INLINE StringRepresentation* getStringRepresentation() const { return m_buffer; }
- const char* begin() const
- {
- return getData();
- }
- const char* end() const
- {
- return getData() + getLength();
- }
+ /// Detach the representation (will leave string as empty). Rep ref count will remain unchanged.
+ SLANG_FORCE_INLINE StringRepresentation* detachStringRepresentation()
+ {
+ return m_buffer.detach();
+ }
- void append(int32_t value, int radix = 10);
- void append(uint32_t value, int radix = 10);
- void append(int64_t value, int radix = 10);
- void append(uint64_t value, int radix = 10);
- void append(float val, const char* format = "%g");
- void append(double val, const char* format = "%g");
+ const char* begin() const { return getData(); }
+ const char* end() const { return getData() + getLength(); }
- // Padded hex representations
- void append(StableHashCode32 val);
- void append(StableHashCode64 val);
+ void append(int32_t value, int radix = 10);
+ void append(uint32_t value, int radix = 10);
+ void append(int64_t value, int radix = 10);
+ void append(uint64_t value, int radix = 10);
+ void append(float val, const char* format = "%g");
+ void append(double val, const char* format = "%g");
- void append(char const* str);
- void append(char const* str, size_t len);
- void append(const char* textBegin, char const* textEnd);
- void append(char chr);
- void append(String const& str);
- void append(StringSlice const& slice);
- void append(UnownedStringSlice const& slice);
+ // Padded hex representations
+ void append(StableHashCode32 val);
+ void append(StableHashCode64 val);
- /// Append a character (to remove ambiguity with other integral types)
- void appendChar(char chr);
+ void append(char const* str);
+ void append(char const* str, size_t len);
+ void append(const char* textBegin, char const* textEnd);
+ void append(char chr);
+ void append(String const& str);
+ void append(StringSlice const& slice);
+ void append(UnownedStringSlice const& slice);
- /// Append the specified char count times
- void appendRepeatedChar(char chr, Index count);
+ /// Append a character (to remove ambiguity with other integral types)
+ void appendChar(char chr);
- String(const char* str)
- {
- append(str);
+ /// Append the specified char count times
+ void appendRepeatedChar(char chr, Index count);
- }
- String(const char* textBegin, char const* textEnd)
- {
- append(textBegin, textEnd);
- }
+ String(const char* str) { append(str); }
+ String(const char* textBegin, char const* textEnd) { append(textBegin, textEnd); }
- // Make all String ctors from a numeric explicit, to avoid unexpected/unnecessary conversions
- explicit String(int32_t val, int radix = 10)
- {
- append(val, radix);
- }
- explicit String(uint32_t val, int radix = 10)
- {
- append(val, radix);
- }
- explicit String(int64_t val, int radix = 10)
- {
- append(val, radix);
- }
- explicit String(uint64_t val, int radix = 10)
- {
- append(val, radix);
- }
- explicit String(StableHashCode32 val)
- {
- append(val);
- }
- explicit String(StableHashCode64 val)
- {
- append(val);
- }
- explicit String(float val, const char* format = "%g")
- {
- append(val, format);
- }
- explicit String(double val, const char* format = "%g")
- {
- append(val, format);
- }
+ // Make all String ctors from a numeric explicit, to avoid unexpected/unnecessary conversions
+ explicit String(int32_t val, int radix = 10) { append(val, radix); }
+ explicit String(uint32_t val, int radix = 10) { append(val, radix); }
+ explicit String(int64_t val, int radix = 10) { append(val, radix); }
+ explicit String(uint64_t val, int radix = 10) { append(val, radix); }
+ explicit String(StableHashCode32 val) { append(val); }
+ explicit String(StableHashCode64 val) { append(val); }
+ explicit String(float val, const char* format = "%g") { append(val, format); }
+ explicit String(double val, const char* format = "%g") { append(val, format); }
- explicit String(char chr)
- {
- appendChar(chr);
- }
- String(String const& str)
- {
- m_buffer = str.m_buffer;
- }
- String(String&& other)
- {
- m_buffer = _Move(other.m_buffer);
- }
+ explicit String(char chr) { appendChar(chr); }
+ String(String const& str) { m_buffer = str.m_buffer; }
+ String(String&& other) { m_buffer = _Move(other.m_buffer); }
- String(StringSlice const& slice)
- {
- append(slice);
- }
+ String(StringSlice const& slice) { append(slice); }
- String(UnownedStringSlice const& slice)
- {
- append(slice);
- }
+ String(UnownedStringSlice const& slice) { append(slice); }
- ~String()
- {
- m_buffer.setNull();
- }
+ ~String() { m_buffer.setNull(); }
- String& operator=(const String& str)
- {
- m_buffer = str.m_buffer;
- return *this;
- }
- String& operator=(String&& other)
- {
- m_buffer = _Move(other.m_buffer);
- return *this;
- }
- char operator[](Index id) const
- {
- SLANG_ASSERT(id >= 0 && id < getLength());
- // Silence a pedantic warning on GCC
+ String& operator=(const String& str)
+ {
+ m_buffer = str.m_buffer;
+ return *this;
+ }
+ String& operator=(String&& other)
+ {
+ m_buffer = _Move(other.m_buffer);
+ return *this;
+ }
+ char operator[](Index id) const
+ {
+ SLANG_ASSERT(id >= 0 && id < getLength());
+ // Silence a pedantic warning on GCC
#if __GNUC__
- if(id < 0) __builtin_unreachable();
+ if (id < 0)
+ __builtin_unreachable();
#endif
- return begin()[id];
- }
+ return begin()[id];
+ }
- Index getLength() const
- {
- return m_buffer ? m_buffer->getLength() : 0;
- }
- /// Make the length of the string the amount specified. Must be less than current size
- void reduceLength(Index length);
-
- friend String operator+(const char*op1, const String & op2);
- friend String operator+(const String & op1, const char * op2);
- friend String operator+(const String & op1, const String & op2);
-
- StringSlice trimStart() const
- {
- if (!m_buffer)
- return StringSlice();
- Index startIndex = 0;
- const char*const data = getData();
- while (startIndex < getLength() &&
- (data[startIndex] == ' ' || data[startIndex] == '\t' || data[startIndex] == '\r' || data[startIndex] == '\n'))
- startIndex++;
- return StringSlice(m_buffer, startIndex, getLength());
- }
+ Index getLength() const { return m_buffer ? m_buffer->getLength() : 0; }
+ /// Make the length of the string the amount specified. Must be less than current size
+ void reduceLength(Index length);
- StringSlice trimEnd() const
- {
- if (!m_buffer)
- return StringSlice();
+ friend String operator+(const char* op1, const String& op2);
+ friend String operator+(const String& op1, const char* op2);
+ friend String operator+(const String& op1, const String& op2);
- Index endIndex = getLength();
- const char*const data = getData();
- while (endIndex > 0 &&
- (data[endIndex-1] == ' ' || data[endIndex-1] == '\t' || data[endIndex-1] == '\r' || data[endIndex-1] == '\n'))
- endIndex--;
+ StringSlice trimStart() const
+ {
+ if (!m_buffer)
+ return StringSlice();
+ Index startIndex = 0;
+ const char* const data = getData();
+ while (startIndex < getLength() && (data[startIndex] == ' ' || data[startIndex] == '\t' ||
+ data[startIndex] == '\r' || data[startIndex] == '\n'))
+ startIndex++;
+ return StringSlice(m_buffer, startIndex, getLength());
+ }
- return StringSlice(m_buffer, 0, endIndex);
- }
+ StringSlice trimEnd() const
+ {
+ if (!m_buffer)
+ return StringSlice();
- StringSlice trim() const
- {
- if (!m_buffer)
- return StringSlice();
-
- Index startIndex = 0;
- const char*const data = getData();
- while (startIndex < getLength() &&
- (data[startIndex] == ' ' || data[startIndex] == '\t' || data[startIndex] == '\r' || data[startIndex] == '\n'))
- startIndex++;
- Index endIndex = getLength();
- while (endIndex > startIndex &&
- (data[endIndex-1] == ' ' || data[endIndex-1] == '\t' || data[endIndex-1] == '\r' || data[endIndex-1] == '\n'))
- endIndex--;
-
- return StringSlice(m_buffer, startIndex, endIndex);
- }
+ Index endIndex = getLength();
+ const char* const data = getData();
+ while (endIndex > 0 && (data[endIndex - 1] == ' ' || data[endIndex - 1] == '\t' ||
+ data[endIndex - 1] == '\r' || data[endIndex - 1] == '\n'))
+ endIndex--;
- StringSlice subString(Index id, Index len) const
- {
- if (len == 0)
- return StringSlice();
+ return StringSlice(m_buffer, 0, endIndex);
+ }
+
+ StringSlice trim() const
+ {
+ if (!m_buffer)
+ return StringSlice();
+
+ Index startIndex = 0;
+ const char* const data = getData();
+ while (startIndex < getLength() && (data[startIndex] == ' ' || data[startIndex] == '\t' ||
+ data[startIndex] == '\r' || data[startIndex] == '\n'))
+ startIndex++;
+ Index endIndex = getLength();
+ while (endIndex > startIndex && (data[endIndex - 1] == ' ' || data[endIndex - 1] == '\t' ||
+ data[endIndex - 1] == '\r' || data[endIndex - 1] == '\n'))
+ endIndex--;
+
+ return StringSlice(m_buffer, startIndex, endIndex);
+ }
+
+ StringSlice subString(Index id, Index len) const
+ {
+ if (len == 0)
+ return StringSlice();
- if (id + len > getLength())
- len = getLength() - id;
+ if (id + len > getLength())
+ len = getLength() - id;
#if _DEBUG
- if (id < 0 || id >= getLength() || (id + len) > getLength())
- SLANG_ASSERT_FAILURE("SubString: index out of range.");
- if (len < 0)
- SLANG_ASSERT_FAILURE("SubString: length less than zero.");
+ if (id < 0 || id >= getLength() || (id + len) > getLength())
+ SLANG_ASSERT_FAILURE("SubString: index out of range.");
+ if (len < 0)
+ SLANG_ASSERT_FAILURE("SubString: length less than zero.");
#endif
- return StringSlice(m_buffer, id, id + len);
- }
+ return StringSlice(m_buffer, id, id + len);
+ }
- char const* getBuffer() const
- {
- return getData();
- }
+ char const* getBuffer() const { return getData(); }
- OSString toWString(Index* len = 0) const;
+ OSString toWString(Index* len = 0) const;
- bool equals(const String& str, bool caseSensitive = true)
+ bool equals(const String& str, bool caseSensitive = true)
+ {
+ if (caseSensitive)
+ return (strcmp(begin(), str.begin()) == 0);
+ else
{
- if (caseSensitive)
- return (strcmp(begin(), str.begin()) == 0);
- else
- {
#ifdef _MSC_VER
- return (_stricmp(begin(), str.begin()) == 0);
+ return (_stricmp(begin(), str.begin()) == 0);
#else
- return (strcasecmp(begin(), str.begin()) == 0);
+ return (strcasecmp(begin(), str.begin()) == 0);
#endif
- }
- }
- bool operator==(const char* strbuffer) const
- {
- return (strcmp(begin(), strbuffer) == 0);
- }
-
- bool operator==(const String& str) const
- {
- return (strcmp(begin(), str.begin()) == 0);
- }
- bool operator!=(const char* strbuffer) const
- {
- return (strcmp(begin(), strbuffer) != 0);
- }
- bool operator!=(const String& str) const
- {
- return (strcmp(begin(), str.begin()) != 0);
- }
- bool operator>(const String& str) const
- {
- return (strcmp(begin(), str.begin()) > 0);
- }
- bool operator<(const String& str) const
- {
- return (strcmp(begin(), str.begin()) < 0);
- }
- bool operator>=(const String& str) const
- {
- return (strcmp(begin(), str.begin()) >= 0);
- }
- bool operator<=(const String& str) const
- {
- return (strcmp(begin(), str.begin()) <= 0);
}
+ }
+ bool operator==(const char* strbuffer) const { return (strcmp(begin(), strbuffer) == 0); }
- SLANG_FORCE_INLINE bool operator==(const UnownedStringSlice& slice) const { return getUnownedSlice() == slice; }
- SLANG_FORCE_INLINE bool operator!=(const UnownedStringSlice& slice) const { return getUnownedSlice() != slice; }
+ bool operator==(const String& str) const { return (strcmp(begin(), str.begin()) == 0); }
+ bool operator!=(const char* strbuffer) const { return (strcmp(begin(), strbuffer) != 0); }
+ bool operator!=(const String& str) const { return (strcmp(begin(), str.begin()) != 0); }
+ bool operator>(const String& str) const { return (strcmp(begin(), str.begin()) > 0); }
+ bool operator<(const String& str) const { return (strcmp(begin(), str.begin()) < 0); }
+ bool operator>=(const String& str) const { return (strcmp(begin(), str.begin()) >= 0); }
+ bool operator<=(const String& str) const { return (strcmp(begin(), str.begin()) <= 0); }
- String toUpper() const
- {
- String result;
- for (auto c : *this)
- {
- char d = (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;
- result.append(d);
- }
- return result;
- }
+ SLANG_FORCE_INLINE bool operator==(const UnownedStringSlice& slice) const
+ {
+ return getUnownedSlice() == slice;
+ }
+ SLANG_FORCE_INLINE bool operator!=(const UnownedStringSlice& slice) const
+ {
+ return getUnownedSlice() != slice;
+ }
- String toLower() const
+ String toUpper() const
+ {
+ String result;
+ for (auto c : *this)
{
- String result;
- for (auto c : *this)
- {
- char d = (c >= 'A' && c <= 'Z') ? (c - ('A' - 'a')) : c;
- result.append(d);
- }
- return result;
+ char d = (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;
+ result.append(d);
}
+ return result;
+ }
- Index indexOf(const char* str, Index id) const // String str
+ String toLower() const
+ {
+ String result;
+ for (auto c : *this)
{
- if (id >= getLength())
- return Index(-1);
- auto findRs = strstr(begin() + id, str);
- Index res = findRs ? findRs - begin() : Index(-1);
- return res;
+ char d = (c >= 'A' && c <= 'Z') ? (c - ('A' - 'a')) : c;
+ result.append(d);
}
+ return result;
+ }
- Index indexOf(const String& str, Index id) const
- {
- return indexOf(str.begin(), id);
- }
+ Index indexOf(const char* str, Index id) const // String str
+ {
+ if (id >= getLength())
+ return Index(-1);
+ auto findRs = strstr(begin() + id, str);
+ Index res = findRs ? findRs - begin() : Index(-1);
+ return res;
+ }
- Index indexOf(const char* str) const
- {
- return indexOf(str, 0);
- }
+ Index indexOf(const String& str, Index id) const { return indexOf(str.begin(), id); }
- Index indexOf(const String& str) const
- {
- return indexOf(str.begin(), 0);
- }
+ Index indexOf(const char* str) const { return indexOf(str, 0); }
- void swapWith(String& other)
- {
- m_buffer.swapWith(other.m_buffer);
- }
+ Index indexOf(const String& str) const { return indexOf(str.begin(), 0); }
- Index indexOf(char ch, Index id) const
- {
- const Index length = getLength();
- SLANG_ASSERT(id >= 0 && id <= length);
+ void swapWith(String& other) { m_buffer.swapWith(other.m_buffer); }
- if (!m_buffer)
- return Index(-1);
+ Index indexOf(char ch, Index id) const
+ {
+ const Index length = getLength();
+ SLANG_ASSERT(id >= 0 && id <= length);
- const char* data = getData();
- for (Index i = id; i < length; i++)
- if (data[i] == ch)
- return i;
+ if (!m_buffer)
return Index(-1);
- }
-
- Index indexOf(char ch) const
- {
- return indexOf(ch, 0);
- }
- Index lastIndexOf(char ch) const
- {
- const Index length = getLength();
- const char* data = getData();
+ const char* data = getData();
+ for (Index i = id; i < length; i++)
+ if (data[i] == ch)
+ return i;
+ return Index(-1);
+ }
- for (Index i = length - 1; i >= 0; --i)
- if (data[i] == ch)
- return i;
- return Index(-1);
- }
+ Index indexOf(char ch) const { return indexOf(ch, 0); }
- bool startsWith(const char* str) const
- {
- if (!m_buffer)
- return false;
- Index strLen = Index(::strlen(str));
- if (strLen > getLength())
- return false;
+ Index lastIndexOf(char ch) const
+ {
+ const Index length = getLength();
+ const char* data = getData();
- const char*const data = getData();
+ for (Index i = length - 1; i >= 0; --i)
+ if (data[i] == ch)
+ return i;
+ return Index(-1);
+ }
- for (Index i = 0; i < strLen; i++)
- if (str[i] != data[i])
- return false;
- return true;
- }
+ bool startsWith(const char* str) const
+ {
+ if (!m_buffer)
+ return false;
+ Index strLen = Index(::strlen(str));
+ if (strLen > getLength())
+ return false;
- bool startsWith(const String& str) const
- {
- return startsWith(str.begin());
- }
+ const char* const data = getData();
- bool endsWith(char const* str) const // String str
- {
- if (!m_buffer)
+ for (Index i = 0; i < strLen; i++)
+ if (str[i] != data[i])
return false;
+ return true;
+ }
+
+ bool startsWith(const String& str) const { return startsWith(str.begin()); }
+
+ bool endsWith(char const* str) const // String str
+ {
+ if (!m_buffer)
+ return false;
- const Index strLen = Index(::strlen(str));
- const Index len = getLength();
+ const Index strLen = Index(::strlen(str));
+ const Index len = getLength();
- if (strLen > len)
+ if (strLen > len)
+ return false;
+ const char* data = getData();
+ for (Index i = strLen; i > 0; i--)
+ if (str[i - 1] != data[len - strLen + i - 1])
return false;
- const char* data = getData();
- for (Index i = strLen; i > 0; i--)
- if (str[i-1] != data[len - strLen + i-1])
- return false;
- return true;
- }
+ return true;
+ }
- bool endsWith(const String& str) const
- {
- return endsWith(str.begin());
- }
+ bool endsWith(const String& str) const { return endsWith(str.begin()); }
- bool contains(const char* str) const // String str
- {
- return m_buffer && indexOf(str) != Index(-1);
- }
+ bool contains(const char* str) const // String str
+ {
+ return m_buffer && indexOf(str) != Index(-1);
+ }
- bool contains(const String& str) const
- {
- return contains(str.begin());
- }
+ bool contains(const String& str) const { return contains(str.begin()); }
- static constexpr bool kHasUniformHash = true;
- HashCode64 getHashCode() const
- {
- return Slang::getHashCode(StringRepresentation::asSlice(m_buffer));
- }
+ static constexpr bool kHasUniformHash = true;
+ HashCode64 getHashCode() const
+ {
+ return Slang::getHashCode(StringRepresentation::asSlice(m_buffer));
+ }
- UnownedStringSlice getUnownedSlice() const
- {
- return StringRepresentation::asSlice(m_buffer);
- }
- };
+ UnownedStringSlice getUnownedSlice() const { return StringRepresentation::asSlice(m_buffer); }
+};
- class SLANG_RT_API StringBuilder : public String
+class SLANG_RT_API StringBuilder : public String
+{
+private:
+ enum
{
- private:
- enum { InitialSize = 1024 };
- public:
- typedef String Super;
- using Super::append;
+ InitialSize = 1024
+ };
- explicit StringBuilder(UInt bufferSize = InitialSize)
- {
- ensureUniqueStorageWithCapacity(bufferSize);
- }
+public:
+ typedef String Super;
+ using Super::append;
- void ensureCapacity(UInt size)
- {
- ensureUniqueStorageWithCapacity(size);
- }
- StringBuilder& operator << (char ch)
- {
- appendChar(ch);
- return *this;
- }
- StringBuilder& operator << (Int32 val)
- {
- append(val);
- return *this;
- }
- StringBuilder& operator << (UInt32 val)
- {
- append(val);
- return *this;
- }
- StringBuilder& operator << (Int64 val)
- {
- append(val);
- return *this;
- }
- StringBuilder& operator << (UInt64 val)
- {
- append(val);
- return *this;
- }
- StringBuilder& operator << (float val)
- {
- append(val);
- return *this;
- }
- StringBuilder& operator << (double val)
- {
- append(val);
- return *this;
- }
- StringBuilder& operator << (const char* str)
- {
- append(str, strlen(str));
- return *this;
- }
- StringBuilder& operator << (const String& str)
- {
- append(str);
- return *this;
- }
- StringBuilder& operator << (UnownedStringSlice const& str)
- {
- append(str);
- return *this;
- }
- StringBuilder& operator << (const _EndLine)
- {
- appendChar('\n');
- return *this;
- }
+ explicit StringBuilder(UInt bufferSize = InitialSize)
+ {
+ ensureUniqueStorageWithCapacity(bufferSize);
+ }
- String toString()
- {
- return *this;
- }
+ void ensureCapacity(UInt size) { ensureUniqueStorageWithCapacity(size); }
+ StringBuilder& operator<<(char ch)
+ {
+ appendChar(ch);
+ return *this;
+ }
+ StringBuilder& operator<<(Int32 val)
+ {
+ append(val);
+ return *this;
+ }
+ StringBuilder& operator<<(UInt32 val)
+ {
+ append(val);
+ return *this;
+ }
+ StringBuilder& operator<<(Int64 val)
+ {
+ append(val);
+ return *this;
+ }
+ StringBuilder& operator<<(UInt64 val)
+ {
+ append(val);
+ return *this;
+ }
+ StringBuilder& operator<<(float val)
+ {
+ append(val);
+ return *this;
+ }
+ StringBuilder& operator<<(double val)
+ {
+ append(val);
+ return *this;
+ }
+ StringBuilder& operator<<(const char* str)
+ {
+ append(str, strlen(str));
+ return *this;
+ }
+ StringBuilder& operator<<(const String& str)
+ {
+ append(str);
+ return *this;
+ }
+ StringBuilder& operator<<(UnownedStringSlice const& str)
+ {
+ append(str);
+ return *this;
+ }
+ StringBuilder& operator<<(const _EndLine)
+ {
+ appendChar('\n');
+ return *this;
+ }
- String produceString()
- {
- return *this;
- }
+ String toString() { return *this; }
+
+ String produceString() { return *this; }
#if 0
void Remove(int id, int len)
@@ -1000,20 +883,17 @@ namespace Slang
length -= actualDelLength;
}
#endif
- friend std::ostream& operator<< (std::ostream& stream, const String& s);
+ friend std::ostream& operator<<(std::ostream& stream, const String& s);
- void clear()
- {
- m_buffer.setNull();
- }
- };
+ void clear() { m_buffer.setNull(); }
+};
- int stringToInt(const String& str, int radix = 10);
- unsigned int stringToUInt(const String& str, int radix = 10);
- double stringToDouble(const String& str);
- float stringToFloat(const String& str);
-}
+int stringToInt(const String& str, int radix = 10);
+unsigned int stringToUInt(const String& str, int radix = 10);
+double stringToDouble(const String& str);
+float stringToFloat(const String& str);
+} // namespace Slang
-std::ostream& operator<< (std::ostream& stream, const Slang::String& s);
+std::ostream& operator<<(std::ostream& stream, const Slang::String& s);
#endif