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) {
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) {
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
118protected:
119 // Must be constructed through string_view. This allows for using the string
120 // class for both owned and non-owned strings, which can reduce allocations
121 // when code conditionally should store a literal or an owned string.
122 // Making this constructor private forces the code to explicitly create a
123 // string_view which emphasizes that the string won't be freed by the class.
124 string(const char *str)
125 : m_str(nullptr)
126 , m_const_str(str ? str : "")
127 , m_length(str ? ecs_os_strlen(str) : 0) { }
128
129 char *m_str = nullptr;
130 const char *m_const_str;
131 ecs_size_t m_length;
132};
133
134// For consistency, the API returns a string_view where it could have returned
135// a const char*, so an application won't have to think about whether to call
136// c_str() or not. The string_view is a thin wrapper around a string that forces
137// the API to indicate explicitly when a string is owned or not.
139 explicit string_view(const char *str)
140 : string(str) { }
141};
142
143}