Logo AND Algorithmique Numérique Distribuée

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