Flecs v3.2
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 : m_str(nullptr)
16 , m_const_str("")
17 , m_length(0) { }
18
19 explicit string(char *str)
20 : m_str(str)
21 , m_const_str(str ? str : "")
22 , m_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 (m_str) {
30 ecs_os_free(m_str);
31 }
32 }
33
34 string(string&& str) noexcept {
35 ecs_os_free(m_str);
36 m_str = str.m_str;
37 m_const_str = str.m_const_str;
38 m_length = str.m_length;
39 str.m_str = nullptr;
40 }
41
42 operator const char*() const {
43 return m_const_str;
44 }
45
46 string& operator=(string&& str) noexcept {
47 ecs_os_free(m_str);
48 m_str = str.m_str;
49 m_const_str = str.m_const_str;
50 m_length = str.m_length;
51 str.m_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.m_const_str == m_const_str) {
61 return true;
62 }
63
64 if (!m_const_str || !str.m_const_str) {
65 return false;
66 }
67
68 if (str.m_length != m_length) {
69 return false;
70 }
71
72 return ecs_os_strcmp(str, m_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 (m_const_str == str) {
81 return true;
82 }
83
84 if (!m_const_str || !str) {
85 return false;
86 }
87
88 return ecs_os_strcmp(str, m_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 m_const_str;
97 }
98
99 std::size_t length() const {
100 return static_cast<std::size_t>(m_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(m_str);
114 m_str = nullptr;
115 m_const_str = nullptr;
116 }
117
118 bool contains(const char *substr) {
119 if (m_const_str) {
120 return strstr(m_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 : m_str(nullptr)
134 , m_const_str(str ? str : "")
135 , m_length(str ? ecs_os_strlen(str) : 0) { }
136
137 char *m_str = nullptr;
138 const char *m_const_str;
139 ecs_size_t m_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}