stlab.adobe.com Adobe Systems Incorporated
string.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2005-2007 Adobe Systems Incorporated
3  Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
4  or a copy at http://stlab.adobe.com/licenses.html)
5 */
6 
7 /*************************************************************************************************/
8 
9 #ifndef ADOBE_STRING_HPP
10 #define ADOBE_STRING_HPP
11 
12 #include <adobe/config.hpp>
13 
14 #include <cstring>
15 #include <functional>
16 #include <iterator>
17 #include <string>
18 
19 #if defined(ADOBE_STD_SERIALIZATION)
20 #include <iosfwd>
21 #endif
22 
23 #include <boost/cstdint.hpp>
24 #include <boost/operators.hpp>
25 #include <boost/static_assert.hpp>
26 #include <boost/utility.hpp>
27 
28 #include <adobe/cstring.hpp>
29 #include <adobe/string_fwd.hpp>
30 #include <adobe/typeinfo.hpp>
31 #include <adobe/vector.hpp>
32 
33 /*************************************************************************************************/
34 
35 namespace std {
36 
37 /*************************************************************************************************/
38 
46 
47 template<typename CharT, class Traits, class Allocator>
48 typename std::basic_string<CharT, Traits, Allocator>&
49  operator << ( std::basic_string<CharT, Traits, Allocator>& out,
50  const std::basic_string<CharT, Traits, Allocator>& in)
51 {
52  typename std::basic_string<CharT, Traits, Allocator>::size_type required(in.size() + out.size());
53 
54  if (required > out.capacity()) out.reserve((std::max)(out.capacity() * 2, required));
55 
56  out += in;
57  return out;
58 }
59 
60 /*************************************************************************************************/
61 
63 template<typename CharT, class Traits, class Allocator>
64 typename std::basic_string<CharT, Traits, Allocator>&
65  operator << (std::basic_string<CharT, Traits, Allocator>& out_str, const CharT* in_str)
66 {
67  typename std::basic_string<CharT, Traits, Allocator>::size_type required(std::strlen(in_str) + out_str.size());
68 
69  if (required > out_str.capacity()) out_str.reserve((std::max)(out_str.capacity() * 2, required));
70 
71  out_str += in_str;
72  return out_str;
73 }
74 
76 
77 /*************************************************************************************************/
78 
79 } // namespace std
80 
81 /*************************************************************************************************/
82 
83 namespace adobe {
84 
85 /*************************************************************************************************/
86 
125 inline std::string make_string(const char* a, const char * b)
126 {
127  std::string result;
128  result.reserve(std::strlen(a) + std::strlen(b));
129  result += a;
130  result += b;
131  return result;
132 }
133 
134 /*************************************************************************************************/
135 
136 inline std::string make_string(const char* a, const char * b, const char* c)
137 {
138  std::string result;
139  result.reserve(std::strlen(a) + std::strlen(b) + std::strlen(b));
140  result += a;
141  result += b;
142  result += c;
143  return result;
144 }
145 
147 
148 /*************************************************************************************************/
149 
151 struct str_less_t : std::binary_function<const char*, const char*, bool>
152 {
153  bool operator()(const char* x, const char* y) const
154  { return adobe::strcmp(x, y) < 0; }
155 };
156 
157 
158 
159 /*************************************************************************************************/
160 
161 } // namespace adobe
162 
163 /*************************************************************************************************/
164 
165 namespace adobe {
166 namespace version_1 {
167 
172 /*************************************************************************************************/
173 
174 // Move this to some appropriate file.
176 template <typename Derived>
177 class empty_base_t { }; // Empty base to reduce size of adobe::string
178 
179 /*************************************************************************************************/
180 
192 class string_t : boost::totally_ordered<string_t, string_t, empty_base_t<string_t> >
193 {
194  public:
195  typedef char value_type;
196  typedef char* pointer;
197  typedef const char* const_pointer;
198  typedef char& reference;
199  typedef const char& const_reference;
200  typedef std::size_t size_type;
201  typedef std::ptrdiff_t difference_type;
202  typedef char* iterator;
203  typedef const char* const_iterator;
204  typedef std::reverse_iterator<char*> reverse_iterator;
205  typedef std::reverse_iterator<const char*> const_reverse_iterator;
206 
207  private:
209 
210  storage_type storage_m;
211 
212  /*
213  NOTE (eberdahl@adobe.com): Because c_str is required to return a null-terminated sequence,
214  we ensure that the storage vector is always null-terminated. This means that the storage
215  is always either empty or contains one extra character to hold the null-character.
216  */
217  template <typename ForwardIterator>
218  void assign(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag)
219  {
220  storage_type tmp;
221  if (first != last)
222  {
223  const size_type len(std::distance(first, last));
224  tmp.reserve(len + 1);
225  tmp.insert(tmp.end(), first, last);
226  tmp.push_back(char(0));
227  }
228  storage_m.swap(tmp);
229  }
230 
231  template <typename InputIterator>
232  void assign(InputIterator first, InputIterator last, std::input_iterator_tag)
233  {
234  storage_type tmp;
235  if (first != last)
236  {
237  tmp.insert(tmp.end(), first, last);
238  tmp.push_back(char(0));
239  }
240  storage_m.swap(tmp);
241  }
242 
243  template <typename Iterator>
244  void assign(Iterator first, Iterator last)
245  {
246  assign(first, last,
247  typename std::iterator_traits<Iterator>::iterator_category());
248  }
249 
250  operator int() const; // for safe bool conversion
251 
252  public:
256  string_t() { }
257 
261  string_t(const string_t& s) : storage_m(s.storage_m) { }
262 
266  string_t(move_from<string_t> x) : storage_m(adobe::move(x.source.storage_m)) { }
267 
273  string_t(const char* s);
274 
281  string_t(const char* s, std::size_t length);
282 
289  template <typename Iterator>
290  string_t(Iterator first, Iterator last)
291  { assign(first, last); }
292 
298  string_t(const std::string& s);
299 
303  ~string_t() { }
304 
309  string_t& operator=(string_t s) { storage_m = adobe::move(s.storage_m); return *this; }
310 
314  /*
315  NOTE (eberdahl@adobe.com): This function was created to support extracting std::string
316  from any_regular_t (N.B. any_regular_t stores strings as string_t). Using conversion
317  member functions may not be the best way to support the required conversion. Until
318  any_regular_t changes the way it extracts data, we'll need this function.
319  */
320  operator std::string() const
321  { return std::string(begin(), end()); }
322 
327  const char* c_str() const
328  { return empty() ? "" : &storage_m[0]; }
329 
333  void push_back(value_type c);
334 
338  template <typename Iterator>
339  void append(Iterator first, Iterator last)
340  {
341  if (first != last)
342  {
343  if (!storage_m.empty())
344  storage_m.pop_back();
345 
346  storage_m.insert(storage_m.end(), first, last);
347  storage_m.push_back(0);
348  }
349  }
350 
354  void append(const string_t& s)
355  { append(s.begin(), s.end()); }
356 
360  void append(const char* s)
361  { append(s, s + std::strlen(s)); }
362 
366  void append(const char* s, std::size_t length)
367  { append(s, s + length); }
368 
372  void append(const std::string& s)
373  { append(s.begin(), s.end()); }
374 
379  { append(s); return *this; }
380 
384  string_t& operator+=(const char* s)
385  { append(s); return *this; }
386 
390  string_t& operator+=(const std::string& s)
391  { append(s); return *this; }
392 
397  { return storage_m.begin(); }
398 
403  { return storage_m.empty() ? storage_m.end() : boost::prior(storage_m.end()); }
404 
409  { return const_reverse_iterator(end()); }
410 
415 
420  size_type capacity() const;
421 
428  { storage_m.reserve(0 == n ? 0 : n + 1); }
429 
433  void clear()
434  { storage_m.clear(); }
435 
439  size_type size() const
440  { return storage_m.empty() ? 0 : storage_m.size() - 1; }
441 
445  bool empty() const
446  { return storage_m.empty(); }
447 
451  operator bool() const { return !empty(); }
452 
456  void swap(string_t& s)
457  { storage_m.swap(s.storage_m); }
458 
459  friend bool operator==(const string_t& x, const string_t& y)
460  {
461  return x.storage_m == y.storage_m;
462  }
463 
464  friend bool operator<(const string_t& x, const string_t& y)
465  {
466  return x.storage_m < y.storage_m;
467  }
468 
469  friend inline void swap(string_t& x, string_t& y)
470  { x.storage_m.swap(y.storage_m); }
471 };
472 
478 inline string_t operator+(string_t s1, const string_t& s2) { return adobe::move(s1 += s2); }
479 inline string_t operator+(string_t s1, const std::string& s2) { return adobe::move(s1 += s2); }
480 inline string_t operator+(string_t s1, const char* s2) { return adobe::move(s1 += s2); }
481 
482 /*************************************************************************************************/
483 
484 #if defined(ADOBE_STD_SERIALIZATION)
485 std::ostream& operator<<(std::ostream& os, const string_t& t);
486 #endif
487 
488 /*************************************************************************************************/
489 
500 class string16_t : boost::totally_ordered<string16_t, string16_t, empty_base_t<string16_t> >
501 {
502 public:
503  typedef boost::uint16_t value_type;
504  typedef boost::uint16_t* pointer;
505  typedef const boost::uint16_t* const_pointer;
506  typedef boost::uint16_t& reference;
507  typedef const boost::uint16_t& const_reference;
508  typedef std::size_t size_type;
509  typedef std::ptrdiff_t difference_type;
510  typedef boost::uint16_t* iterator;
511  typedef const boost::uint16_t* const_iterator;
512  typedef std::reverse_iterator<boost::uint16_t*> reverse_iterator;
513  typedef std::reverse_iterator<const boost::uint16_t*> const_reverse_iterator;
514 
515 private:
517 
518  storage_type storage_m;
519 
520  /*
521  NOTE (eberdahl@adobe.com): Because c_str is required to return a null-terminated sequence,
522  we ensure that the storage vector is always null-terminated. This means that the storage
523  is always either empty or contains one extra character to hold the null-character.
524  */
525  template <typename ForwardIterator>
526  void assign(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag)
527  {
528  storage_type tmp;
529  if (first != last)
530  {
531  const size_type len(std::distance(first, last));
532  tmp.reserve(len + 1);
533  tmp.insert(tmp.end(), first, last);
534  tmp.push_back(boost::uint16_t(0));
535  }
536  storage_m.swap(tmp);
537  }
538 
539  template <typename InputIterator>
540  void assign(InputIterator first, InputIterator last, std::input_iterator_tag)
541  {
542  storage_type tmp;
543  if (first != last)
544  {
545  tmp.insert(tmp.end(), first, last);
546  tmp.push_back(boost::uint16_t(0));
547  }
548  storage_m.swap(tmp);
549  }
550 
551  template <typename Iterator>
552  void assign(Iterator first, Iterator last)
553  {
554  assign(first, last,
555  typename std::iterator_traits<Iterator>::iterator_category());
556  }
557 
558  operator int() const; // for safe bool conversion
559 
560 public:
565 
569  string16_t(const string16_t& s) : storage_m(s.storage_m) { }
570 
574  string16_t(move_from<string16_t> x) : storage_m(adobe::move(x.source.storage_m)) { }
575 
581  string16_t(const boost::uint16_t* s);
582 
589  string16_t(const boost::uint16_t* s, std::size_t length);
590 
597  template <typename Iterator>
598  string16_t(Iterator first, Iterator last)
599  { assign(first, last); }
600 
605 
610  { storage_m = adobe::move(s.storage_m); return *this; }
611 
616  const boost::uint16_t* c_str() const;
617 
621  void push_back(value_type c);
622 
626  template <typename Iterator>
627  void append(Iterator first, Iterator last)
628  {
629  if (first != last)
630  {
631  if (!storage_m.empty())
632  storage_m.pop_back();
633 
634  storage_m.insert(storage_m.end(), first, last);
635  storage_m.push_back(0);
636  }
637  }
638 
642  void append(const string16_t& s)
643  { append(s.begin(), s.end()); }
644 
648  void append(const boost::uint16_t* s);
649 
653  void append(const boost::uint16_t* s, std::size_t length)
654  { append(s, s + length); }
655 
660  { append(s); return *this; }
661 
665  string16_t& operator+=(const boost::uint16_t* s)
666  { append(s); return *this; }
667 
672  { return storage_m.begin(); }
673 
678  { return storage_m.empty() ? storage_m.end() : boost::prior(storage_m.end()); }
679 
684  { return const_reverse_iterator(end()); }
685 
690  { return const_reverse_iterator(begin()); }
691 
696  size_type capacity() const;
697 
704  { storage_m.reserve(0 == n ? 0 : n + 1); }
705 
709  void clear()
710  { storage_m.clear(); }
711 
715  size_type size() const
716  { return storage_m.empty() ? 0 : storage_m.size() - 1; }
717 
721  bool empty() const
722  { return storage_m.empty(); }
723 
727  operator bool() const { return !empty(); }
728 
732  void swap(string16_t& s)
733  { storage_m.swap(s.storage_m); }
734 
735  friend bool operator==(const string16_t& x, const string16_t& y)
736  {
737  return x.storage_m == y.storage_m;
738  }
739 
740  friend bool operator<(const string16_t& x, const string16_t& y)
741  {
742  return x.storage_m < y.storage_m;
743  }
744 
745  friend inline void swap(string16_t& x, string16_t& y) { x.storage_m.swap(y.storage_m); }
746 };
747 
754 inline string16_t operator+(string16_t s1, const string16_t& s2) { return adobe::move(s1 += s2); }
755 inline string16_t operator+(string16_t s1, const boost::uint16_t* s2) { return adobe::move(s1 += s2); }
756 
758 
759 /*************************************************************************************************/
760 
761 BOOST_STATIC_ASSERT(sizeof(string_t) == sizeof(vector<char>));
763 
764 /*************************************************************************************************/
765 
766 } // namespace version_1
767 
768 /*************************************************************************************************/
769 
770 using version_1::string_t;
771 using version_1::string16_t;
772 
773 /*************************************************************************************************/
774 
775 } // namespace adobe
776 
777 /*************************************************************************************************/
778 
779 ADOBE_NAME_TYPE_0("string_t:version_1:adobe", adobe::version_1::string_t)
780 ADOBE_NAME_TYPE_0("string16_t:version_1:adobe", adobe::version_1::string16_t)
781 
782 ADOBE_SHORT_NAME_TYPE('s','t','r','g', adobe::version_1::string_t)
783 ADOBE_SHORT_NAME_TYPE('s','t','1','6', adobe::version_1::string16_t)
784 
785 /*************************************************************************************************/
786 
787 namespace boost {
788 
789 template <>
790 struct has_nothrow_constructor<adobe::version_1::string_t> : boost::mpl::true_ { };
791 
792 template <>
793 struct has_nothrow_constructor<adobe::version_1::string16_t> : boost::mpl::true_ { };
794 
795 } // namespace boost
796 
797 /*************************************************************************************************/
798 
799 #endif
800 
801 /*************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google