diff --git a/deps/ox/ox-docs.md b/deps/ox/ox-docs.md index 7a29d545..d0dbe93a 100644 --- a/deps/ox/ox-docs.md +++ b/deps/ox/ox-docs.md @@ -181,6 +181,169 @@ variant for creating a non-const value. * ```OX_REQUIRE_M``` - OX_REQUIRE Mutable +### Ox String Types + +Ox has six different major string types. +These types are divided into two categories: store types and view types. + +String stores maintain a copy of the string data, whereas view types only +maintain a reference to the data. +Views should be used where you otherwise might use a const reference to a +string store type. + +#### String Store Types + +##### String + +```ox::String```, or really ```ox::BasicString```, is Ox's version of +```std::string```. +Like ```std::string```, ```String``` allocates to store the string data. +Also like ```std::string```, ```String``` allows for small string +optimization for strings under 8 bytes. +Unlike ```std::string```, the template that ```String``` is based on, +```BasicString```, takes a parameter that allows adjusting to different size +small string buffers. +```ox::String``` is an alias to ```ox::BasicString<8>```. + +```cpp +// s can hold up to 100 bytes, plus one for a null terminator before allocating +ox::BasicString<100> s; +``` +Also ulike ```std::string```, ```String``` has an explicit C-string conversion +constructor. +This prevents accidental instantiations of ```String```. + +Consider the following: + +```cpp +void fStd(std::string const&); +void fOx(ox::String const&); + +int main() { + // implicit and silent instantiation of std::string, which includes an + // allocation + fStd("123456789"); + // Will fail to compile: + fOx("123456789"); + // But explicit String instantiation will work: + fOx(ox::String{"123456789"}); +} +``` + +##### IString + +```IString```, or "inline string", is like ```BasicString```, but it will cut +off strings that exceed that limit. + +```cpp +ox::IString<5> s; // s can hold up to 5 characters, plus a null terminator +s = "12345"; // valid +s = "123456"; // will compile and run, but will get cut off at '5' +``` + +##### StringParam + +```StringParam``` is a weird type. +Because ```String::String(const char*)``` is explicit, it becomes a pain for +functions to take ```String```s. + +```cpp +struct Type { + ox::String m_s; + explicit Type(ox::String p): m_s(std::move(p)) { + } +}; + +void f() { + ox::String s{"asdf"}; + Type t1{"asdf"}; // invalid - will not compile + Type t2{s}; // invalid - will not compile + Type t3{std::move(s)}; // valid + Type t4{ox::String{"asdf"}}; // valid +} +``` + +```StringParam``` has implicit conversion constructors, and will appropriately +move from r-value ```String```s. +It will create a ```String``` if not passed ownership of an existing +```String```. + +```StringParam``` can access the string as a view through the ```view()``` +function, and the ```String``` inside can be accessed by moving from the +```StringParams```. + +```cpp +struct Type { + ox::String m_s; + explicit Type(ox::StringParam p): m_s(std::move(p)) { + } +}; + +void f() { + ox::String s{"asdf"}; + Type t1{"asdf"}; // valid + Type t2{s}; // valid + Type t3{std::move(s)}; // valid +} +``` + +#### String View Types + +##### StringView + +```ox::StringView``` is Ox's version of ```std::string_view```. +```StringView``` contains a pointer to a string, along with its size. + +This should be the normal type taken when a function needs a string that will +exist until it returns. + +##### CStringView + +```CStringView``` is like ```StringView```, but it comes with the promise that +the string ends with a null terminator. +Accordingly, it has a ```c_str()``` function in addition to the ```data()``` +function that ```StringView``` has. + +```CStringView``` should be used when wrapping a C API that only takes C +strings. + +##### StringLiteral + +```StringLiteral``` is a string view type, but it kind of straddles the line +between view and store types. +Creating a ```StringLiteral``` is a promise that you are passing a string +literal into the constructor. +This means you can treat it like a store, that can be safely used as a copy of +the data. +Functions that take ```StringLiteral```s are allowed to assume that the data +will have no lifetime concerns and hold onto it without any need to make a +copy. +It has a consteval constructor to enforce the promise that it is a compile time +string. + +```cpp +void f(ox::StringLiteral const&); + +int main() { + f("123456789"); // valid + f(ox::String{"123456789"}.c_str()); // invalid - will not compile +} +``` + +#### Other Variants + +There are a few convenience aliases as well. + +* StringCR = String const& +* StringViewCR = StringView const& +* CStringViewCR = CStringView const& + +String views do not generally need const references, but it does make debugging +easier, as we can skip the constructor call if a string view already exists. + +These kind of aliases probably should not exist for most types, but strings are +fundamental and ease of use is desirable. + ### Logging and Output Ox provides for logging and debug prints via the ```oxTrace```, ```oxDebug```, and ```oxError``` macros.