Rename CString->String and Update Implementation#202
Rename CString->String and Update Implementation#202Mozz3d wants to merge 14 commits intowopss:masterfrom
CString->String and Update Implementation#202Conversation
And outdated use of `CString` in the `function_registration/Main.cpp` example file
- Fix some more incorrect forward decls - Remove a mostly unnecessary function that led to a circular dependency (something to resolve later) - Manual casts to avoid warnings
Also moved impls to inl file to avoid circular dependency
idk why pre commit isnt working
wopss
left a comment
There was a problem hiding this comment.
I took a quick look at the class API, will do more in-depth review later.
include/RED4ext/String.hpp
Outdated
| String(const std::string& aStr, const Memory::IAllocator* aAllocator = nullptr); | ||
| ~String(); | ||
|
|
||
| operator std::string() const; |
There was a problem hiding this comment.
| operator std::string() const; | |
| [[nodiscard]] operator std::string() const; |
include/RED4ext/String.hpp
Outdated
| operator std::string() const; | ||
|
|
||
| [[nodiscard]] operator std::string_view() const noexcept; |
There was a problem hiding this comment.
I would put the conversion operators after the operator= or even at the end of all operators, but that's my preference, you can ignore it.
include/RED4ext/String.hpp
Outdated
| String(const String& aOther); | ||
| String(String&& aOther) noexcept; | ||
| String(const std::string& aStr, const Memory::IAllocator* aAllocator = nullptr); | ||
| ~String(); |
There was a problem hiding this comment.
| ~String(); | |
| ~String(); |
include/RED4ext/String.hpp
Outdated
| Reference operator[](SizeType aIndex) noexcept; | ||
| ConstReference operator[](SizeType aIndex) const noexcept; | ||
|
|
||
| String& Assign(ConstPointer aStr, SizeType aSize); |
There was a problem hiding this comment.
I would remove this, since StringView does the job here.
include/RED4ext/String.hpp
Outdated
|
|
||
| operator std::string() const; | ||
|
|
||
| [[nodiscard]] operator std::string_view() const noexcept; |
There was a problem hiding this comment.
I don't remember if we spoke about this, but should [[nodiscard]] be on the same line or new line?
There was a problem hiding this comment.
I don't remember if we ever discussed it.
There was a problem hiding this comment.
What is your preference in this case? I would prefer it on a new line.
| { | ||
| } | ||
|
|
||
| StringView(const String& aStr) noexcept; |
There was a problem hiding this comment.
You are missing the move operations.
| { | ||
| } | ||
|
|
||
| StringView(const String& aStr) noexcept; |
| bool operator==(const String& aRhs) const noexcept; | ||
| bool operator!=(const String& aRhs) const noexcept; |
There was a problem hiding this comment.
| bool operator==(const String& aRhs) const noexcept; | |
| bool operator!=(const String& aRhs) const noexcept; | |
| constexpr bool operator==(const String& aRhs) const noexcept; | |
| constexpr bool operator!=(const String& aRhs) const noexcept; |
| constexpr operator bool() const noexcept | ||
| { | ||
| return !IsEmpty(); | ||
| } |
There was a problem hiding this comment.
Same comment as above about implicit conversions.
| [[nodiscard]] constexpr bool Compare(StringView aOther) const noexcept | ||
| { | ||
| if (IsEmpty() && aOther.IsEmpty()) | ||
| return true; |
There was a problem hiding this comment.
What exactly is the rule on brackets? Evidently, I'm not clear on it
There was a problem hiding this comment.
Better for maintenance as scope is ready to add more statements, some logs when debugging, easier to read, etc.
include/RED4ext/String.hpp
Outdated
| String(ConstPointer aStr, const Memory::IAllocator* aAllocator = nullptr); | ||
| String(const String& aOther); | ||
| String(String&& aOther) noexcept; | ||
| String(const std::string& aStr, const Memory::IAllocator* aAllocator = nullptr); |
There was a problem hiding this comment.
Should have one for string_view too.
include/RED4ext/String.hpp
Outdated
| operator std::string() const; | ||
|
|
||
| [[nodiscard]] operator std::string_view() const noexcept; |
There was a problem hiding this comment.
Generally yes, I consider implicit conversions unsafe in the first place. But I can't think of any good examples for this case.
include/RED4ext/String.hpp
Outdated
| [[nodiscard]] bool IsBackInternal() const noexcept; | ||
| [[nodiscard]] bool IsBackAllocated() const noexcept; | ||
| [[nodiscard]] bool IsBackViewing() const noexcept; | ||
| [[nodiscard]] bool IsBackExternal() const noexcept; |
There was a problem hiding this comment.
I agree, these methods should be private (for internal use) of removed.
include/RED4ext/String.hpp
Outdated
| #pragma endregion | ||
| union Storage | ||
| { | ||
| enum class BackType : uint32_t |
There was a problem hiding this comment.
Perhaps StorageMode is a better name.
include/RED4ext/String.hpp
Outdated
| Internal = 0, // owned, inline | ||
| Allocated = 1, // owned, external | ||
| Viewing = 2 // unowned, external |
There was a problem hiding this comment.
We can continue to use Inline, same term is used for Variant class.
For other two I can suggest DynamicallyAllocated and ExternallyAllocated.
include/RED4ext/String.hpp
Outdated
| { | ||
| Internal = 0, // owned, inline | ||
| Allocated = 1, // owned, external | ||
| Viewing = 2 // unowned, external |
There was a problem hiding this comment.
BTW, how to create externally allocated String right now?
There was a problem hiding this comment.
It's all done in SetCapacity() (1744572317)
It also handles the transition from inline to allocated and vice versa
There was a problem hiding this comment.
I don't get it. How it can transfer ownership in SetCapacity? This doesn't make sense.
There was a problem hiding this comment.
I checked the function. It doesn't do anything if storage is set to external as expected.
There was a problem hiding this comment.
Wdym? Like from viewing to allocated? It doesn't
There was a problem hiding this comment.
Yeah, my bad, I didn't understand what you were asking.
String can go from inline -> allocated and back, but it can't take ownership if viewing
There was a problem hiding this comment.
So when you said `owned, external you meant "allocated on heap, managed by this class"?
include/RED4ext/String.hpp
Outdated
| { | ||
| Internal = 0, // owned, inline | ||
| Allocated = 1, // owned, external | ||
| Viewing = 2 // unowned, external |
There was a problem hiding this comment.
So when you said `owned, external you meant "allocated on heap, managed by this class"?
include/RED4ext/String.hpp
Outdated
| { | ||
| Internal = 0, // owned, inline | ||
| Allocated = 1, // owned, external | ||
| Viewing = 2 // unowned, external |
There was a problem hiding this comment.
What is viewing? How can a string have an unowned string?
There was a problem hiding this comment.
When string is in that mode it's pretty much no different in functionality than StringView
String manages a ptr and size for the data, but does not own anything about the data
There was a problem hiding this comment.
That's really odd, is this even used in game? Maybe they share this with the StringView?
There was a problem hiding this comment.
I looked into this much more in-depth, and it turns out my initial assumption wasn't necessarily right. This mode is used in the binary but only ever with stack-allocated scratch buffers. So it's more accurately a "scratch mode."
While the String still doesn't own the memory, it looks like it's always used as an in-place "API" over a piece of the stack for building.
I personally don't like this; it's dangerous and awkward, but it is what it is.
There was a problem hiding this comment.
Such a use case really should be a dedicated type. IDK why they decided to cram it into the default String, but it's probably because they didn't have time to rebuild the string API
How do we want to do this?
There was a problem hiding this comment.
Would it be possible that they have a different class for this? Something like a nonmovable and noncopyable string.
Also, is there a pattern to that? Maybe they have more small string optimizations.
How do we want to do this?
We should just mention it here, but never allow for it to be used in the SDK.
There was a problem hiding this comment.
I think the most dangerous part is mutability. We could allow it as const String only with a static helper function.
As for use cases, they seem to use it for const strings for their own interfaces that require String, e.g. "NULL" for RTTI/serialization.
String: - Extract `String::Storage` union from within `String` and rename to `StringStorage` - Extract `String::Storage::BackType` to standalone enum and rename to `EStringMode` - Rename `EStringMode` fields to better reflect usage - Fix allocator constness - Remove uses of `ConstPointer, SizeType` methods in favor of `StringView` - Add `std::string_view` constructor - Removed implicit conversion operators - Removed `CalcHash()` - Removed unnecessary STL compliant definitions - Removed mode check methods in favor of more explicit expressions - Always use brackets StringView: - Document default move/copy constructors - Make methods revolving `String` constexpr - Always use brackets
I imagined this being an issue
I figured out pre-commit hook!
No description provided.