string.hpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 00004 or a copy at http://stlab.adobe.com/licenses.html) 00005 */ 00006 00007 /*************************************************************************************************/ 00008 00009 #ifndef ADOBE_STRING_HPP 00010 #define ADOBE_STRING_HPP 00011 00012 #include <adobe/config.hpp> 00013 00014 #include <cstring> 00015 #include <functional> 00016 #include <iterator> 00017 #include <string> 00018 00019 #if defined(ADOBE_STD_SERIALIZATION) 00020 #include <iosfwd> 00021 #endif 00022 00023 #include <boost/cstdint.hpp> 00024 #include <boost/operators.hpp> 00025 #include <boost/static_assert.hpp> 00026 #include <boost/utility.hpp> 00027 00028 #include <adobe/cstring.hpp> 00029 #include <adobe/string_fwd.hpp> 00030 #include <adobe/typeinfo.hpp> 00031 #include <adobe/vector.hpp> 00032 00033 /*************************************************************************************************/ 00034 00035 namespace std { 00036 00037 /*************************************************************************************************/ 00038 00046 00047 template<typename CharT, class Traits, class Allocator> 00048 typename std::basic_string<CharT, Traits, Allocator>& 00049 operator << ( std::basic_string<CharT, Traits, Allocator>& out, 00050 const std::basic_string<CharT, Traits, Allocator>& in) 00051 { 00052 typename std::basic_string<CharT, Traits, Allocator>::size_type required(in.size() + out.size()); 00053 00054 if (required > out.capacity()) out.reserve((std::max)(out.capacity() * 2, required)); 00055 00056 out += in; 00057 return out; 00058 } 00059 00060 /*************************************************************************************************/ 00061 00063 template<typename CharT, class Traits, class Allocator> 00064 typename std::basic_string<CharT, Traits, Allocator>& 00065 operator << (std::basic_string<CharT, Traits, Allocator>& out_str, const CharT* in_str) 00066 { 00067 typename std::basic_string<CharT, Traits, Allocator>::size_type required(std::strlen(in_str) + out_str.size()); 00068 00069 if (required > out_str.capacity()) out_str.reserve((std::max)(out_str.capacity() * 2, required)); 00070 00071 out_str += in_str; 00072 return out_str; 00073 } 00074 00076 00077 /*************************************************************************************************/ 00078 00079 } // namespace std 00080 00081 /*************************************************************************************************/ 00082 00083 namespace adobe { 00084 00085 /*************************************************************************************************/ 00086 00125 inline std::string make_string(const char* a, const char * b) 00126 { 00127 std::string result; 00128 result.reserve(std::strlen(a) + std::strlen(b)); 00129 result += a; 00130 result += b; 00131 return result; 00132 } 00133 00134 /*************************************************************************************************/ 00135 00136 inline std::string make_string(const char* a, const char * b, const char* c) 00137 { 00138 std::string result; 00139 result.reserve(std::strlen(a) + std::strlen(b) + std::strlen(b)); 00140 result += a; 00141 result += b; 00142 result += c; 00143 return result; 00144 } 00145 00147 00148 /*************************************************************************************************/ 00149 00151 struct str_less_t : std::binary_function<const char*, const char*, bool> 00152 { 00153 bool operator()(const char* x, const char* y) const 00154 { return adobe::strcmp(x, y) < 0; } 00155 }; 00156 00157 00158 00159 /*************************************************************************************************/ 00160 00161 } // namespace adobe 00162 00163 /*************************************************************************************************/ 00164 00165 namespace adobe { 00166 namespace version_1 { 00167 00172 /*************************************************************************************************/ 00173 00174 // Move this to some appropriate file. 00176 template <typename Derived> 00177 class empty_base_t { }; // Empty base to reduce size of adobe::string 00178 00179 /*************************************************************************************************/ 00180 00192 class string_t : boost::totally_ordered<string_t, string_t, empty_base_t<string_t> > 00193 { 00194 public: 00195 typedef char value_type; 00196 typedef char* pointer; 00197 typedef const char* const_pointer; 00198 typedef char& reference; 00199 typedef const char& const_reference; 00200 typedef std::size_t size_type; 00201 typedef std::ptrdiff_t difference_type; 00202 typedef char* iterator; 00203 typedef const char* const_iterator; 00204 typedef std::reverse_iterator<char*> reverse_iterator; 00205 typedef std::reverse_iterator<const char*> const_reverse_iterator; 00206 00207 private: 00208 typedef vector<value_type> storage_type; 00209 00210 storage_type storage_m; 00211 00212 /* 00213 NOTE (eberdahl@adobe.com): Because c_str is required to return a null-terminated sequence, 00214 we ensure that the storage vector is always null-terminated. This means that the storage 00215 is always either empty or contains one extra character to hold the null-character. 00216 */ 00217 template <typename ForwardIterator> 00218 void assign(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) 00219 { 00220 storage_type tmp; 00221 if (first != last) 00222 { 00223 const size_type len(std::distance(first, last)); 00224 tmp.reserve(len + 1); 00225 tmp.insert(tmp.end(), first, last); 00226 tmp.push_back(char(0)); 00227 } 00228 storage_m.swap(tmp); 00229 } 00230 00231 template <typename InputIterator> 00232 void assign(InputIterator first, InputIterator last, std::input_iterator_tag) 00233 { 00234 storage_type tmp; 00235 if (first != last) 00236 { 00237 tmp.insert(tmp.end(), first, last); 00238 tmp.push_back(char(0)); 00239 } 00240 storage_m.swap(tmp); 00241 } 00242 00243 template <typename Iterator> 00244 void assign(Iterator first, Iterator last) 00245 { 00246 assign(first, last, 00247 typename std::iterator_traits<Iterator>::iterator_category()); 00248 } 00249 00250 operator int() const; // for safe bool conversion 00251 00252 public: 00256 string_t() { } 00257 00261 string_t(const string_t& s) : storage_m(s.storage_m) { } 00262 00266 string_t(move_from<string_t> x) : storage_m(adobe::move(x.source.storage_m)) { } 00267 00273 string_t(const char* s); 00274 00281 string_t(const char* s, std::size_t length); 00282 00289 template <typename Iterator> 00290 string_t(Iterator first, Iterator last) 00291 { assign(first, last); } 00292 00298 string_t(const std::string& s); 00299 00303 ~string_t() { } 00304 00309 string_t& operator=(string_t s) { storage_m = adobe::move(s.storage_m); return *this; } 00310 00314 /* 00315 NOTE (eberdahl@adobe.com): This function was created to support extracting std::string 00316 from any_regular_t (N.B. any_regular_t stores strings as string_t). Using conversion 00317 member functions may not be the best way to support the required conversion. Until 00318 any_regular_t changes the way it extracts data, we'll need this function. 00319 */ 00320 operator std::string() const 00321 { return std::string(begin(), end()); } 00322 00327 const char* c_str() const 00328 { return empty() ? "" : &storage_m[0]; } 00329 00333 void push_back(value_type c); 00334 00338 template <typename Iterator> 00339 void append(Iterator first, Iterator last) 00340 { 00341 if (first != last) 00342 { 00343 if (!storage_m.empty()) 00344 storage_m.pop_back(); 00345 00346 storage_m.insert(storage_m.end(), first, last); 00347 storage_m.push_back(0); 00348 } 00349 } 00350 00354 void append(const string_t& s) 00355 { append(s.begin(), s.end()); } 00356 00360 void append(const char* s) 00361 { append(s, s + std::strlen(s)); } 00362 00366 void append(const char* s, std::size_t length) 00367 { append(s, s + length); } 00368 00372 void append(const std::string& s) 00373 { append(s.begin(), s.end()); } 00374 00378 string_t& operator+=(const string_t& s) 00379 { append(s); return *this; } 00380 00384 string_t& operator+=(const char* s) 00385 { append(s); return *this; } 00386 00390 string_t& operator+=(const std::string& s) 00391 { append(s); return *this; } 00392 00396 const_iterator begin() const 00397 { return storage_m.begin(); } 00398 00402 const_iterator end() const 00403 { return storage_m.empty() ? storage_m.end() : boost::prior(storage_m.end()); } 00404 00408 const_reverse_iterator rbegin() const 00409 { return const_reverse_iterator(end()); } 00410 00414 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } 00415 00420 size_type capacity() const; 00421 00427 void reserve(size_type n) 00428 { storage_m.reserve(0 == n ? 0 : n + 1); } 00429 00433 void clear() 00434 { storage_m.clear(); } 00435 00439 size_type size() const 00440 { return storage_m.empty() ? 0 : storage_m.size() - 1; } 00441 00445 bool empty() const 00446 { return storage_m.empty(); } 00447 00451 operator bool() const { return !empty(); } 00452 00456 void swap(string_t& s) 00457 { storage_m.swap(s.storage_m); } 00458 00459 friend bool operator==(const string_t& x, const string_t& y) 00460 { 00461 return x.storage_m == y.storage_m; 00462 } 00463 00464 friend bool operator<(const string_t& x, const string_t& y) 00465 { 00466 return x.storage_m < y.storage_m; 00467 } 00468 00469 friend inline void swap(string_t& x, string_t& y) 00470 { x.storage_m.swap(y.storage_m); } 00471 }; 00472 00478 inline string_t operator+(string_t s1, const string_t& s2) { return adobe::move(s1 += s2); } 00479 inline string_t operator+(string_t s1, const std::string& s2) { return adobe::move(s1 += s2); } 00480 inline string_t operator+(string_t s1, const char* s2) { return adobe::move(s1 += s2); } 00481 00482 /*************************************************************************************************/ 00483 00484 #if defined(ADOBE_STD_SERIALIZATION) 00485 std::ostream& operator<<(std::ostream& os, const string_t& t); 00486 #endif 00487 00488 /*************************************************************************************************/ 00489 00500 class string16_t : boost::totally_ordered<string16_t, string16_t, empty_base_t<string16_t> > 00501 { 00502 public: 00503 typedef boost::uint16_t value_type; 00504 typedef boost::uint16_t* pointer; 00505 typedef const boost::uint16_t* const_pointer; 00506 typedef boost::uint16_t& reference; 00507 typedef const boost::uint16_t& const_reference; 00508 typedef std::size_t size_type; 00509 typedef std::ptrdiff_t difference_type; 00510 typedef boost::uint16_t* iterator; 00511 typedef const boost::uint16_t* const_iterator; 00512 typedef std::reverse_iterator<boost::uint16_t*> reverse_iterator; 00513 typedef std::reverse_iterator<const boost::uint16_t*> const_reverse_iterator; 00514 00515 private: 00516 typedef vector<value_type> storage_type; 00517 00518 storage_type storage_m; 00519 00520 /* 00521 NOTE (eberdahl@adobe.com): Because c_str is required to return a null-terminated sequence, 00522 we ensure that the storage vector is always null-terminated. This means that the storage 00523 is always either empty or contains one extra character to hold the null-character. 00524 */ 00525 template <typename ForwardIterator> 00526 void assign(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) 00527 { 00528 storage_type tmp; 00529 if (first != last) 00530 { 00531 const size_type len(std::distance(first, last)); 00532 tmp.reserve(len + 1); 00533 tmp.insert(tmp.end(), first, last); 00534 tmp.push_back(boost::uint16_t(0)); 00535 } 00536 storage_m.swap(tmp); 00537 } 00538 00539 template <typename InputIterator> 00540 void assign(InputIterator first, InputIterator last, std::input_iterator_tag) 00541 { 00542 storage_type tmp; 00543 if (first != last) 00544 { 00545 tmp.insert(tmp.end(), first, last); 00546 tmp.push_back(boost::uint16_t(0)); 00547 } 00548 storage_m.swap(tmp); 00549 } 00550 00551 template <typename Iterator> 00552 void assign(Iterator first, Iterator last) 00553 { 00554 assign(first, last, 00555 typename std::iterator_traits<Iterator>::iterator_category()); 00556 } 00557 00558 operator int() const; // for safe bool conversion 00559 00560 public: 00564 string16_t() { } 00565 00569 string16_t(const string16_t& s) : storage_m(s.storage_m) { } 00570 00574 string16_t(move_from<string16_t> x) : storage_m(adobe::move(x.source.storage_m)) { } 00575 00581 string16_t(const boost::uint16_t* s); 00582 00589 string16_t(const boost::uint16_t* s, std::size_t length); 00590 00597 template <typename Iterator> 00598 string16_t(Iterator first, Iterator last) 00599 { assign(first, last); } 00600 00604 ~string16_t() { } 00605 00609 string16_t& operator=(string16_t s) 00610 { storage_m = adobe::move(s.storage_m); return *this; } 00611 00616 const boost::uint16_t* c_str() const; 00617 00621 void push_back(value_type c); 00622 00626 template <typename Iterator> 00627 void append(Iterator first, Iterator last) 00628 { 00629 if (first != last) 00630 { 00631 if (!storage_m.empty()) 00632 storage_m.pop_back(); 00633 00634 storage_m.insert(storage_m.end(), first, last); 00635 storage_m.push_back(0); 00636 } 00637 } 00638 00642 void append(const string16_t& s) 00643 { append(s.begin(), s.end()); } 00644 00648 void append(const boost::uint16_t* s); 00649 00653 void append(const boost::uint16_t* s, std::size_t length) 00654 { append(s, s + length); } 00655 00659 string16_t& operator+=(const string16_t& s) 00660 { append(s); return *this; } 00661 00665 string16_t& operator+=(const boost::uint16_t* s) 00666 { append(s); return *this; } 00667 00671 const_iterator begin() const 00672 { return storage_m.begin(); } 00673 00677 const_iterator end() const 00678 { return storage_m.empty() ? storage_m.end() : boost::prior(storage_m.end()); } 00679 00683 const_reverse_iterator rbegin() const 00684 { return const_reverse_iterator(end()); } 00685 00689 const_reverse_iterator rend() const 00690 { return const_reverse_iterator(begin()); } 00691 00696 size_type capacity() const; 00697 00703 void reserve(size_type n) 00704 { storage_m.reserve(0 == n ? 0 : n + 1); } 00705 00709 void clear() 00710 { storage_m.clear(); } 00711 00715 size_type size() const 00716 { return storage_m.empty() ? 0 : storage_m.size() - 1; } 00717 00721 bool empty() const 00722 { return storage_m.empty(); } 00723 00727 operator bool() const { return !empty(); } 00728 00732 void swap(string16_t& s) 00733 { storage_m.swap(s.storage_m); } 00734 00735 friend bool operator==(const string16_t& x, const string16_t& y) 00736 { 00737 return x.storage_m == y.storage_m; 00738 } 00739 00740 friend bool operator<(const string16_t& x, const string16_t& y) 00741 { 00742 return x.storage_m < y.storage_m; 00743 } 00744 00745 friend inline void swap(string16_t& x, string16_t& y) { x.storage_m.swap(y.storage_m); } 00746 }; 00747 00754 inline string16_t operator+(string16_t s1, const string16_t& s2) { return adobe::move(s1 += s2); } 00755 inline string16_t operator+(string16_t s1, const boost::uint16_t* s2) { return adobe::move(s1 += s2); } 00756 00758 00759 /*************************************************************************************************/ 00760 00761 BOOST_STATIC_ASSERT(sizeof(string_t) == sizeof(vector<char>)); 00762 BOOST_STATIC_ASSERT(sizeof(string16_t) == sizeof(vector<boost::uint16_t>)); 00763 00764 /*************************************************************************************************/ 00765 00766 } // namespace version_1 00767 00768 /*************************************************************************************************/ 00769 00770 using version_1::string_t; 00771 using version_1::string16_t; 00772 00773 /*************************************************************************************************/ 00774 00775 } // namespace adobe 00776 00777 /*************************************************************************************************/ 00778 00779 ADOBE_NAME_TYPE_0("string_t:version_1:adobe", adobe::version_1::string_t) 00780 ADOBE_NAME_TYPE_0("string16_t:version_1:adobe", adobe::version_1::string16_t) 00781 00782 ADOBE_SHORT_NAME_TYPE('s','t','r','g', adobe::version_1::string_t) 00783 ADOBE_SHORT_NAME_TYPE('s','t','1','6', adobe::version_1::string16_t) 00784 00785 /*************************************************************************************************/ 00786 00787 namespace boost { 00788 00789 template <> 00790 struct has_nothrow_constructor<adobe::version_1::string_t> : boost::mpl::true_ { }; 00791 00792 template <> 00793 struct has_nothrow_constructor<adobe::version_1::string16_t> : boost::mpl::true_ { }; 00794 00795 } // namespace boost 00796 00797 /*************************************************************************************************/ 00798 00799 #endif 00800 00801 /*************************************************************************************************/ |