Logo AND Algorithmique Numérique Distribuée

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