Logo AND Algorithmique Numérique Distribuée

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