Flecs v4.0
A fast entity component system (ECS) for C & C++
Loading...
Searching...
No Matches
string.hpp
Go to the documentation of this file.
1
6namespace flecs {
7
8struct string_view;
9
10// This removes dependencies on std::string (and therefore STL) and allows the
11// API to return allocated strings without incurring additional allocations when
12// wrapping in an std::string.
13struct string {
14 explicit string()
15 : str_(nullptr)
16 , const_str_("")
17 , length_(0) { }
18
19 explicit string(char *str)
20 : str_(str)
21 , const_str_(str ? str : "")
22 , length_(str ? ecs_os_strlen(str) : 0) { }
23
24 ~string() {
25 // If flecs is included in a binary but is not used, it is possible that
26 // the OS API is not initialized. Calling ecs_os_free in that case could
27 // crash the application during exit. However, if a string has been set
28 // flecs has been used, and OS API should have been initialized.
29 if (str_) {
30 ecs_os_free(str_);
31 }
32 }
33
34 string(string&& str) noexcept {
35 ecs_os_free(str_);
36 str_ = str.str_;
37 const_str_ = str.const_str_;
38 length_ = str.length_;
39 str.str_ = nullptr;
40 }
41
42 operator const char*() const {
43 return const_str_;
44 }
45
46 string& operator=(string&& str) noexcept {
47 ecs_os_free(str_);
48 str_ = str.str_;
49 const_str_ = str.const_str_;
50 length_ = str.length_;
51 str.str_ = nullptr;
52 return *this;
53 }
54
55 // Ban implicit copies/allocations
56 string& operator=(const string& str) = delete;
57 string(const string& str) = delete;
58
59 bool operator==(const flecs::string& str) const {
60 if (str.const_str_ == const_str_) {
61 return true;
62 }
63
64 if (!const_str_ || !str.const_str_) {
65 return false;
66 }
67
68 if (str.length_ != length_) {
69 return false;
70 }
71
72 return ecs_os_strcmp(str, const_str_) == 0;
73 }
74
75 bool operator!=(const flecs::string& str) const {
76 return !(*this == str);
77 }
78
79 bool operator==(const char *str) const {
80 if (const_str_ == str) {
81 return true;
82 }
83
84 if (!const_str_ || !str) {
85 return false;
86 }
87
88 return ecs_os_strcmp(str, const_str_) == 0;
89 }
90
91 bool operator!=(const char *str) const {
92 return !(*this == str);
93 }
94
95 const char* c_str() const {
96 return const_str_;
97 }
98
99 std::size_t length() const {
100 return static_cast<std::size_t>(length_);
101 }
102
103 template <size_t N>
104 static constexpr size_t length( char const (&)[N] ) {
105 return N - 1;
106 }
107
108 std::size_t size() const {
109 return length();
110 }
111
112 void clear() {
113 ecs_os_free(str_);
114 str_ = nullptr;
115 const_str_ = nullptr;
116 }
117
118 bool contains(const char *substr) {
119 if (const_str_) {
120 return strstr(const_str_, substr) != nullptr;
121 } else {
122 return false;
123 }
124 }
125
126protected:
127 // Must be constructed through string_view. This allows for using the string
128 // class for both owned and non-owned strings, which can reduce allocations
129 // when code conditionally should store a literal or an owned string.
130 // Making this constructor private forces the code to explicitly create a
131 // string_view which emphasizes that the string won't be freed by the class.
132 string(const char *str)
133 : str_(nullptr)
134 , const_str_(str ? str : "")
135 , length_(str ? ecs_os_strlen(str) : 0) { }
136
137 char *str_ = nullptr;
138 const char *const_str_;
139 ecs_size_t length_;
140};
141
142// For consistency, the API returns a string_view where it could have returned
143// a const char*, so an application won't have to think about whether to call
144// c_str() or not. The string_view is a thin wrapper around a string that forces
145// the API to indicate explicitly when a string is owned or not.
147 explicit string_view(const char *str)
148 : string(str) { }
149};
150
151}