stlab.adobe.com Adobe Systems Incorporated

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  public:
00254     string_t() { }
00255     
00259     string_t(const string_t& s) : storage_m(s.storage_m) { }
00260     
00264     string_t(move_from<string_t> x) : storage_m(move(x.source.storage_m)) { }
00265 
00271     string_t(const char* s);
00272 
00279     string_t(const char* s, std::size_t length);
00280     
00287     template <typename Iterator>
00288     string_t(Iterator first, Iterator last)
00289         { assign(first, last); }
00290 
00296     string_t(const std::string& s);
00297     
00301     ~string_t() { }
00302 
00307     string_t& operator=(string_t s) { storage_m = move(s.storage_m); return *this; }
00308 
00312     /*
00313         NOTE (eberdahl@adobe.com): This function was created to support extracting std::string
00314         from any_regular_t (N.B. any_regular_t stores strings as string_t). Using conversion
00315         member functions may not be the best way to support the required conversion. Until
00316         any_regular_t changes the way it extracts data, we'll need this function.
00317      */
00318     operator std::string() const
00319         { return std::string(begin(), end()); }
00320     
00325     const char* c_str() const
00326         { return empty() ? "" : &storage_m[0]; }
00327 
00331     void push_back(value_type c);
00332 
00336     template <typename Iterator>
00337     void append(Iterator first, Iterator last)
00338     {
00339         if (first != last)
00340         {
00341             if (!storage_m.empty())
00342                 storage_m.pop_back();
00343             
00344             storage_m.insert(storage_m.end(), first, last);
00345             storage_m.push_back(0);
00346         }
00347     }
00348 
00352     void append(const string_t& s)
00353         { append(s.begin(), s.end()); }
00354 
00358     void append(const char* s)
00359         { append(s, s + std::strlen(s)); }
00360 
00364     void append(const char* s, std::size_t length)
00365         { append(s, s + length); }
00366 
00370     void append(const std::string& s)
00371         { append(s.begin(), s.end()); }
00372 
00376     string_t& operator+=(const string_t& s)
00377         { append(s); return *this; }
00378     
00382     string_t& operator+=(const char* s)
00383         { append(s); return *this; }
00384     
00388     string_t& operator+=(const std::string& s)
00389         { append(s); return *this; }
00390     
00394     const_iterator begin() const
00395         { return storage_m.begin(); }
00396 
00400     const_iterator end() const
00401         { return storage_m.empty() ? storage_m.end() : boost::prior(storage_m.end()); }
00402 
00406     const_reverse_iterator rbegin() const
00407         { return const_reverse_iterator(end()); }
00408 
00412     const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
00413 
00418     size_type capacity() const;
00419     
00425     void reserve(size_type n)
00426         { storage_m.reserve(0 == n ? 0 : n + 1); }
00427 
00431     void clear()
00432         { storage_m.clear(); }
00433     
00437     size_type size() const
00438         { return storage_m.empty() ? 0 : storage_m.size() - 1; }
00439 
00443     bool empty() const
00444         { return storage_m.empty(); }
00445 
00449     void swap(string_t& s)
00450         { storage_m.swap(s.storage_m); }
00451     
00452     friend bool operator==(const string_t& x, const string_t& y)
00453     {
00454         return x.storage_m == y.storage_m;
00455     }
00456 
00457     friend bool operator<(const string_t& x, const string_t& y)
00458     {
00459         return x.storage_m < y.storage_m;
00460     }
00461     
00462     friend inline void swap(string_t& x, string_t& y)
00463         { x.storage_m.swap(y.storage_m); }
00464 };
00465 
00471 inline string_t operator+(string_t s1, const string_t& s2)     { return move(s1 += s2); }
00472 inline string_t operator+(string_t s1, const std::string& s2)  { return move(s1 += s2); }
00473 inline string_t operator+(string_t s1, const char* s2)         { return move(s1 += s2); }
00474 
00475 /*************************************************************************************************/
00476 
00477 #if defined(ADOBE_STD_SERIALIZATION)
00478 std::ostream& operator<<(std::ostream& os, const string_t& t);
00479 #endif
00480 
00481 /*************************************************************************************************/
00482 
00493 class string16_t : boost::totally_ordered<string16_t, string16_t, empty_base_t<string16_t> >
00494 {
00495 public:
00496     typedef boost::uint16_t                               value_type;
00497     typedef boost::uint16_t*                              pointer;
00498     typedef const boost::uint16_t*                        const_pointer;
00499     typedef boost::uint16_t&                              reference;
00500     typedef const boost::uint16_t&                        const_reference;
00501     typedef std::size_t                                   size_type;
00502     typedef std::ptrdiff_t                                difference_type;
00503     typedef boost::uint16_t*                              iterator;
00504     typedef const boost::uint16_t*                        const_iterator;
00505     typedef std::reverse_iterator<boost::uint16_t*>       reverse_iterator;
00506     typedef std::reverse_iterator<const boost::uint16_t*> const_reverse_iterator;
00507     
00508 private:
00509     typedef vector<value_type>                            storage_type;
00510 
00511     storage_type storage_m;
00512     
00513     /*
00514         NOTE (eberdahl@adobe.com): Because c_str is required to return a null-terminated sequence,
00515         we ensure that the storage vector is always null-terminated. This means that the storage
00516         is always either empty or contains one extra character to hold the null-character.
00517      */
00518     template <typename ForwardIterator>
00519     void assign(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag)
00520     {
00521         storage_type tmp;
00522         if (first != last)
00523         {
00524             const size_type len(std::distance(first, last));
00525             tmp.reserve(len + 1);
00526             tmp.insert(tmp.end(), first, last);
00527             tmp.push_back(boost::uint16_t(0));
00528         }
00529         storage_m.swap(tmp);
00530     }
00531     
00532     template <typename InputIterator>
00533     void assign(InputIterator first, InputIterator last, std::input_iterator_tag)
00534     {
00535         storage_type tmp;
00536         if (first != last)
00537         {
00538             tmp.insert(tmp.end(), first, last);
00539             tmp.push_back(boost::uint16_t(0));
00540         }
00541         storage_m.swap(tmp);
00542     }
00543     
00544     template <typename Iterator>
00545     void assign(Iterator first, Iterator last)
00546     {
00547         assign(first, last,
00548                typename std::iterator_traits<Iterator>::iterator_category());
00549     }
00550     
00551 public:
00555     string16_t() { }
00556     
00560     string16_t(const string16_t& s) : storage_m(s.storage_m) { }
00561 
00565     string16_t(move_from<string16_t> x) : storage_m(move(x.source.storage_m)) { }
00566 
00572     string16_t(const boost::uint16_t* s);
00573 
00580     string16_t(const boost::uint16_t* s, std::size_t length);
00581     
00588     template <typename Iterator>
00589     string16_t(Iterator first, Iterator last)
00590         { assign(first, last); }
00591 
00595     ~string16_t() { }
00596     
00600     string16_t& operator=(string16_t s)
00601         { storage_m = move(s.storage_m); return *this; }
00602     
00607     const boost::uint16_t* c_str() const;
00608     
00612     void push_back(value_type c);
00613     
00617     template <typename Iterator>
00618     void append(Iterator first, Iterator last)
00619     {
00620         if (first != last)
00621         {
00622             if (!storage_m.empty())
00623                 storage_m.pop_back();
00624             
00625             storage_m.insert(storage_m.end(), first, last);
00626             storage_m.push_back(0);
00627         }
00628     }
00629     
00633     void append(const string16_t& s)
00634         { append(s.begin(), s.end()); }
00635     
00639     void append(const boost::uint16_t* s);
00640     
00644     void append(const boost::uint16_t* s, std::size_t length)
00645         { append(s, s + length); }
00646     
00650     string16_t& operator+=(const string16_t& s)
00651         { append(s); return *this; }
00652     
00656     string16_t& operator+=(const boost::uint16_t* s)
00657         { append(s); return *this; }
00658     
00662     const_iterator begin() const
00663         { return storage_m.begin(); }
00664     
00668     const_iterator end() const
00669         { return storage_m.empty() ? storage_m.end() : boost::prior(storage_m.end()); }
00670     
00674     const_reverse_iterator rbegin() const
00675         { return const_reverse_iterator(end()); }
00676     
00680     const_reverse_iterator rend() const
00681         { return const_reverse_iterator(begin()); }
00682     
00687     size_type capacity() const;
00688     
00694     void reserve(size_type n)
00695         { storage_m.reserve(0 == n ? 0 : n + 1); }
00696     
00700     void clear()
00701         { storage_m.clear(); }
00702     
00706     size_type size() const
00707         { return storage_m.empty() ? 0 : storage_m.size() - 1; }
00708     
00712     bool empty() const
00713         { return storage_m.empty(); }
00714     
00718     void swap(string16_t& s)
00719         { storage_m.swap(s.storage_m); }
00720     
00721     friend bool operator==(const string16_t& x, const string16_t& y)
00722     {
00723         return x.storage_m == y.storage_m;
00724     }
00725     
00726     friend bool operator<(const string16_t& x, const string16_t& y)
00727     {
00728         return x.storage_m < y.storage_m;
00729     }
00730     
00731     friend inline void swap(string16_t& x, string16_t& y) { x.storage_m.swap(y.storage_m); }
00732 };
00733 
00740 inline string16_t operator+(string16_t s1, const string16_t& s2)      { return move(s1 += s2); }
00741 inline string16_t operator+(string16_t s1, const boost::uint16_t* s2) { return move(s1 += s2); }
00742 
00744 
00745 /*************************************************************************************************/
00746 
00747 BOOST_STATIC_ASSERT(sizeof(string_t) == sizeof(vector<char>));
00748 BOOST_STATIC_ASSERT(sizeof(string16_t) == sizeof(vector<boost::uint16_t>));
00749 
00750 /*************************************************************************************************/
00751 
00752 } // namespace version_1
00753 
00754 /*************************************************************************************************/
00755 
00756 using version_1::string_t;
00757 using version_1::string16_t;
00758 
00759 /*************************************************************************************************/
00760 
00761 } // namespace adobe
00762 
00763 /*************************************************************************************************/
00764 
00765 ADOBE_NAME_TYPE_0("string_t:version_1:adobe", adobe::version_1::string_t)
00766 ADOBE_NAME_TYPE_0("string16_t:version_1:adobe", adobe::version_1::string16_t)
00767 
00768 ADOBE_SHORT_NAME_TYPE('s','t','r','g', adobe::version_1::string_t)
00769 ADOBE_SHORT_NAME_TYPE('s','t','1','6', adobe::version_1::string16_t)
00770 
00771 /*************************************************************************************************/
00772 
00773 namespace boost {
00774 
00775 template <>
00776 struct has_nothrow_constructor<adobe::version_1::string_t> : boost::mpl::true_ { };
00777 
00778 template <>
00779 struct has_nothrow_constructor<adobe::version_1::string16_t> : boost::mpl::true_ { };
00780 
00781 } // namespace boost
00782 
00783 /*************************************************************************************************/
00784 
00785 #endif
00786 
00787 /*************************************************************************************************/

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