Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'models_type_rework_part2_try2' into 'master'
[simgrid.git] / include / xbt / string.hpp
1 /* Copyright (c) 2015-2021. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #ifndef SIMGRID_XBT_STRING_HPP
7 #define SIMGRID_XBT_STRING_HPP
8
9 #include <simgrid/config.h>
10
11 #include <cstdarg>
12 #include <cstdlib>
13 #include <string>
14
15 #if SIMGRID_HAVE_MC
16
17 #include <algorithm>
18 #include <cstddef>
19 #include <cstring>
20 #include <iterator>
21 #include <stdexcept>
22
23 #include <xbt/sysdep.h>
24
25 #endif
26
27 namespace simgrid {
28 namespace xbt {
29
30 /** Create a C++ string from a C-style format
31  *
32  * @ingroup XBT_str
33  */
34 XBT_PUBLIC std::string string_printf(const char* fmt, ...);
35
36 /** Create a C++ string from a C-style format
37  *
38  * @ingroup XBT_str
39  */
40 XBT_PUBLIC std::string string_vprintf(const char* fmt, va_list ap);
41
42 #if SIMGRID_HAVE_MC
43
44 /** POD structure representation of a string
45  */
46 struct string_data {
47   char* data;
48   std::size_t len;
49 };
50
51 /** A std::string-like with well-known representation
52  *
53  *  HACK, this is a (incomplete) replacement for `std::string`.
54  *  It has a fixed POD representation (`simgrid::xbt::string_data`)
55  *  which can be used to easily read the string content from another
56  *  process.
57  *
58  *  The internal representation of a `std::string` is private.
59  *  We could add some code to read this for a given implementation.
60  *  However, even if we focus on GNU libstdc++ with Itanium ABI
61  *  GNU libstdc++ currently has two different ABIs
62  *
63  *  * the pre-C++11 is a pointer to a ref-counted
64  *    string-representation (with support for COW);
65  *
66  *  * the [C++11-conforming implementation](https://gcc.gnu.org/gcc-5/changes.html)
67  *    does not use refcouting/COW but has a small string optimization.
68  */
69 class XBT_PUBLIC string {
70   static char NUL;
71   string_data str;
72
73 public:
74   // Types
75   using size_type       = std::size_t;
76   using reference       = char&;
77   using const_reference = const char&;
78   using iterator        = char*;
79   using const_iterator  = const char*;
80
81   // Dtor
82   ~string()
83   {
84     if (str.data != &NUL)
85       delete[] str.data;
86   }
87
88   // Ctors
89   string(const char* s, size_t size)
90   {
91     if (size == 0) {
92       str.len  = 0;
93       str.data = &NUL;
94     } else {
95       str.len  = size;
96       str.data = new char[str.len + 1];
97       std::copy_n(s, str.len, str.data);
98       str.data[str.len] = '\0';
99     }
100   }
101   string() : string(&NUL, 0) {}
102   explicit string(const char* s) : string(s, strlen(s)) {}
103   string(string const& s) : string(s.c_str(), s.size()) {}
104   string(string&& s) noexcept : str(s.str)
105   {
106     s.str.len  = 0;
107     s.str.data = &NUL;
108   }
109   explicit string(std::string const& s) : string(s.c_str(), s.size()) {}
110
111   // Assign
112   void assign(const char* s, size_t size)
113   {
114     if (str.data != &NUL) {
115       delete[] str.data;
116       str.data = nullptr;
117       str.len  = 0;
118     }
119     if (size != 0) {
120       str.len  = size;
121       str.data = new char[str.len + 1];
122       std::copy_n(s, str.len, str.data);
123       str.data[str.len] = '\0';
124     }
125   }
126
127   // Copy
128   string& operator=(const char* s)
129   {
130     assign(s, std::strlen(s));
131     return *this;
132   }
133   string& operator=(string const& s)
134   {
135     if (this != &s)
136       assign(s.c_str(), s.size());
137     return *this;
138   }
139   string& operator=(std::string const& s)
140   {
141     assign(s.c_str(), s.size());
142     return *this;
143   }
144
145   // Capacity
146   size_t size() const { return str.len; }
147   size_t length() const { return str.len; }
148   bool empty() const { return str.len != 0; }
149   void shrink_to_fit() { /* Being there, but doing nothing */}
150
151   // Element access
152   char* data() { return str.data; }
153   const char* data() const { return str.data; }
154   char* c_str() { return str.data; }
155   const char* c_str() const { return str.data; };
156   reference at(size_type i)
157   {
158     if (i >= size())
159       throw std::out_of_range("Out of range");
160     return data()[i];
161   }
162   const_reference at(size_type i) const
163   {
164     if (i >= size())
165       throw std::out_of_range("Out of range");
166     return data()[i];
167   }
168   reference operator[](size_type i)
169   {
170     return data()[i];
171   }
172   const_reference operator[](size_type i) const
173   {
174     return data()[i];
175   }
176   // Conversion
177   static string_data& to_string_data(string& s) { return s.str; }
178   operator std::string() const { return std::string(this->c_str(), this->size()); }
179
180   // Iterators
181   iterator begin()               { return data(); }
182   iterator end()                 { return data() + size(); }
183   const_iterator begin() const   { return data(); }
184   const_iterator end() const     { return data() + size(); }
185   const_iterator cbegin() const  { return data(); }
186   const_iterator cend() const    { return data() + size(); }
187   // (Missing, reverse iterators)
188
189   // Operations
190   void clear()
191   {
192     str.len  = 0;
193     str.data = &NUL;
194   }
195
196   size_t copy(char* s, size_t len, size_t pos = 0) const
197   {
198     if (pos > str.len)
199       throw std::out_of_range(string_printf("xbt::string::copy with pos > size() (%zu > %zu)", pos, str.len));
200     size_t count = std::min(len, str.len - pos);
201     std::copy_n(str.data + pos, count, s);
202     return count;
203   }
204
205   bool equals(const char* data, std::size_t len) const
206   {
207     return this->size() == len
208       && std::memcmp(this->c_str(), data, len) == 0;
209   }
210
211   bool operator==(string const& that) const
212   {
213     return this->equals(that.c_str(), that.size());
214   }
215   bool operator==(std::string const& that) const
216   {
217     return this->equals(that.c_str(), that.size());
218   }
219   bool operator==(const char* that) const
220   {
221     return this->equals(that, std::strlen(that));
222   }
223
224   template<class X>
225   bool operator!=(X const& that) const
226   {
227     return not (*this == that);
228   }
229
230   // Compare:
231   int compare(const char* data, std::size_t len) const
232   {
233     size_t n = std::min(this->size(), len);
234     int res = memcmp(this->c_str(), data, n);
235     if (res != 0)
236       return res;
237     else if (this->size() == len)
238       return 0;
239     else if (this->size() < len)
240       return -1;
241     else
242       return 1;
243   }
244   int compare(string const& that) const
245   {
246     return this->compare(that.c_str(), that.size());
247   }
248   int compare(std::string const& that) const
249   {
250     return this->compare(that.c_str(), that.size());
251   }
252   int compare(const char* that) const
253   {
254     return this->compare(that, std::strlen(that));
255   }
256
257   // Define < <= >= > in term of compare():
258   template<class X>
259   bool operator<(X const& that) const
260   {
261     return this->compare(that) < 0;
262   }
263   template<class X>
264   bool operator<=(X const& that) const
265   {
266     return this->compare(that) <= 0;
267   }
268   template<class X>
269   bool operator>(X const& that) const
270   {
271     return this->compare(that) > 0;
272   }
273   template<class X>
274   bool operator>=(X const& that) const
275   {
276     return this->compare(that) >= 0;
277   }
278 };
279
280 inline
281 bool operator==(std::string const& a, string const& b)
282 {
283   return b == a;
284 }
285 inline
286 bool operator!=(std::string const& a, string const& b)
287 {
288   return b != a;
289 }
290 inline
291 bool operator<(std::string const& a, string const& b)
292 {
293   return b > a;
294 }
295 inline
296 bool operator<=(std::string const& a, string const& b)
297 {
298   return b >= a;
299 }
300 inline
301 bool operator>(std::string const& a, string const& b)
302 {
303   return b < a;
304 }
305 inline
306 bool operator>=(std::string const& a, string const& b)
307 {
308   return b <= a;
309 }
310
311 #else
312
313 typedef std::string string;
314
315 #endif
316 }
317 }
318
319 #endif