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 #include <boost/cstdint.hpp>
00020 #include <boost/operators.hpp>
00021 #include <boost/static_assert.hpp>
00022 #include <boost/utility.hpp>
00023 
00024 #include <adobe/cstring.hpp>
00025 #include <adobe/string_fwd.hpp>
00026 #include <adobe/typeinfo.hpp>
00027 #include <adobe/vector.hpp>
00028 
00029 /*************************************************************************************************/
00030 
00031 namespace std {
00032 
00033 /*************************************************************************************************/
00034 
00042 
00043 template<typename CharT, class Traits, class Allocator>
00044 typename std::basic_string<CharT, Traits, Allocator>&
00045         operator << (   std::basic_string<CharT, Traits, Allocator>& out,
00046                         const std::basic_string<CharT, Traits, Allocator>& in)
00047 {
00048     typename std::basic_string<CharT, Traits, Allocator>::size_type required(in.size() + out.size());
00049 
00050     if (required > out.capacity()) out.reserve((std::max)(out.capacity() * 2, required));
00051 
00052     out += in;
00053     return out;
00054 }
00055 
00056 /*************************************************************************************************/
00057 
00059 template<typename CharT, class Traits, class Allocator>
00060 typename std::basic_string<CharT, Traits, Allocator>& 
00061         operator << (std::basic_string<CharT, Traits, Allocator>& out_str, const CharT* in_str)
00062 {
00063     typename std::basic_string<CharT, Traits, Allocator>::size_type required(std::strlen(in_str) + out_str.size());
00064 
00065     if (required > out_str.capacity()) out_str.reserve((std::max)(out_str.capacity() * 2, required));
00066 
00067     out_str += in_str;
00068     return out_str;
00069 }
00070 
00072 
00073 /*************************************************************************************************/
00074 
00075 } // namespace std
00076 
00077 /*************************************************************************************************/
00078 
00079 namespace adobe {
00080 
00081 /*************************************************************************************************/
00082 
00121 inline std::string make_string(const char* a, const char * b)
00122 {
00123     std::string result;
00124     result.reserve(std::strlen(a) + std::strlen(b));
00125     result += a;
00126     result += b;
00127     return result;
00128 }
00129 
00130 /*************************************************************************************************/
00131 
00132 inline std::string make_string(const char* a, const char * b, const char* c)
00133 {
00134     std::string result;
00135     result.reserve(std::strlen(a) + std::strlen(b) + std::strlen(b));
00136     result += a;
00137     result += b;
00138     result += c;
00139     return result;
00140 }
00141 
00143 
00144 /*************************************************************************************************/
00145 
00147 struct str_less_t : std::binary_function<const char*, const char*, bool>
00148 {
00149     bool operator()(const char* x, const char* y) const
00150     { return adobe::strcmp(x, y) < 0; }
00151 };
00152 
00153 
00154 
00155 /*************************************************************************************************/
00156 
00157 } // namespace adobe
00158 
00159 /*************************************************************************************************/
00160 
00161 namespace adobe {
00162 namespace version_1 {
00163 
00168 /*************************************************************************************************/
00169 
00170 // Move this to some appropriate file.
00172 template <typename Derived>
00173 class empty_base_t { }; // Empty base to reduce size of adobe::string
00174     
00175 /*************************************************************************************************/
00176 
00188 class string_t : boost::totally_ordered<string_t, string_t, empty_base_t<string_t> >
00189 {
00190  public:
00191     typedef char                               value_type;
00192     typedef char*                              pointer;
00193     typedef const char*                        const_pointer;
00194     typedef char&                              reference;
00195     typedef const char&                        const_reference;
00196     typedef std::size_t                        size_type;
00197     typedef std::ptrdiff_t                     difference_type;
00198     typedef char*                              iterator;
00199     typedef const char*                        const_iterator;
00200     typedef std::reverse_iterator<char*>       reverse_iterator;
00201     typedef std::reverse_iterator<const char*> const_reverse_iterator;
00202 
00203  private:
00204     typedef vector<value_type>                 storage_type;
00205     
00206     storage_type storage_m;
00207 
00208     /*
00209         NOTE (eberdahl@adobe.com): Because c_str is required to return a null-terminated sequence,
00210         we ensure that the storage vector is always null-terminated. This means that the storage
00211         is always either empty or contains one extra character to hold the null-character.
00212     */
00213     template <typename ForwardIterator>
00214     void assign(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag)
00215     {
00216         storage_type tmp;
00217         if (first != last)
00218         {
00219             const size_type len(std::distance(first, last));
00220             tmp.reserve(len + 1);
00221             tmp.insert(tmp.end(), first, last);
00222             tmp.push_back(char(0));
00223         }
00224         storage_m.swap(tmp);
00225     }
00226 
00227     template <typename InputIterator>
00228     void assign(InputIterator first, InputIterator last, std::input_iterator_tag)
00229     {
00230         storage_type tmp;
00231         if (first != last)
00232         {
00233             tmp.insert(tmp.end(), first, last);
00234             tmp.push_back(char(0));
00235         }
00236         storage_m.swap(tmp);
00237     }
00238 
00239     template <typename Iterator>
00240     void assign(Iterator first, Iterator last)
00241     {
00242         assign(first, last,
00243                typename std::iterator_traits<Iterator>::iterator_category());
00244     }
00245     
00246  public:
00250     string_t() { }
00251     
00255     string_t(const string_t& s) : storage_m(s.storage_m) { }
00256     
00260     string_t(move_from<string_t> x) : storage_m(move(x.source.storage_m)) { }
00261 
00267     string_t(const char* s);
00268 
00275     string_t(const char* s, std::size_t length);
00276     
00283     template <typename Iterator>
00284     string_t(Iterator first, Iterator last)
00285         { assign(first, last); }
00286 
00292     string_t(const std::string& s);
00293     
00297     ~string_t() { }
00298 
00303     string_t& operator=(string_t s) { storage_m = move(s.storage_m); return *this; }
00304 
00308     /*
00309         NOTE (eberdahl@adobe.com): This function was created to support extracting std::string
00310         from any_regular_t (N.B. any_regular_t stores strings as string_t). Using conversion
00311         member functions may not be the best way to support the required conversion. Until
00312         any_regular_t changes the way it extracts data, we'll need this function.
00313      */
00314     operator std::string() const
00315         { return std::string(begin(), end()); }
00316     
00321     const char* c_str() const
00322         { return empty() ? "" : &storage_m[0]; }
00323 
00327     void push_back(value_type c);
00328 
00332     template <typename Iterator>
00333     void append(Iterator first, Iterator last)
00334     {
00335         if (first != last)
00336         {
00337             if (!storage_m.empty())
00338                 storage_m.pop_back();
00339             
00340             storage_m.insert(storage_m.end(), first, last);
00341             storage_m.push_back(0);
00342         }
00343     }
00344 
00348     void append(const string_t& s)
00349         { append(s.begin(), s.end()); }
00350 
00354     void append(const char* s)
00355         { append(s, s + std::strlen(s)); }
00356 
00360     void append(const char* s, std::size_t length)
00361         { append(s, s + length); }
00362 
00366     void append(const std::string& s)
00367         { append(s.begin(), s.end()); }
00368 
00372     string_t& operator+=(const string_t& s)
00373         { append(s); return *this; }
00374     
00378     string_t& operator+=(const char* s)
00379         { append(s); return *this; }
00380     
00384     string_t& operator+=(const std::string& s)
00385         { append(s); return *this; }
00386     
00390     const_iterator begin() const
00391         { return storage_m.begin(); }
00392 
00396     const_iterator end() const
00397         { return storage_m.empty() ? storage_m.end() : boost::prior(storage_m.end()); }
00398 
00402     const_reverse_iterator rbegin() const
00403         { return const_reverse_iterator(end()); }
00404 
00408     const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
00409 
00414     size_type capacity() const;
00415     
00421     void reserve(size_type n)
00422         { storage_m.reserve(0 == n ? 0 : n + 1); }
00423 
00427     void clear()
00428         { storage_m.clear(); }
00429     
00433     size_type size() const
00434         { return storage_m.empty() ? 0 : storage_m.size() - 1; }
00435 
00439     bool empty() const
00440         { return storage_m.empty(); }
00441 
00445     void swap(string_t& s)
00446         { storage_m.swap(s.storage_m); }
00447     
00448     friend bool operator==(const string_t& x, const string_t& y)
00449     {
00450         return x.storage_m == y.storage_m;
00451     }
00452 
00453     friend bool operator<(const string_t& x, const string_t& y)
00454     {
00455         return x.storage_m < y.storage_m;
00456     }
00457     
00458     friend inline void swap(string_t& x, string_t& y)
00459         { x.storage_m.swap(y.storage_m); }
00460 };
00461 
00467 inline string_t operator+(string_t s1, const string_t& s2)     { return move(s1 += s2); }
00468 inline string_t operator+(string_t s1, const std::string& s2)  { return move(s1 += s2); }
00469 inline string_t operator+(string_t s1, const char* s2)         { return move(s1 += s2); }
00470 
00471 /*************************************************************************************************/
00472 
00473 #if defined(ADOBE_STD_SERIALIZATION)
00474 inline std::ostream& operator << (std::ostream& os, const string_t& t)
00475 { return os << t.c_str(); }
00476 #endif
00477 
00478 /*************************************************************************************************/
00479 
00490 class string16_t : boost::totally_ordered<string16_t, string16_t, empty_base_t<string16_t> >
00491 {
00492 public:
00493     typedef boost::uint16_t                               value_type;
00494     typedef boost::uint16_t*                              pointer;
00495     typedef const boost::uint16_t*                        const_pointer;
00496     typedef boost::uint16_t&                              reference;
00497     typedef const boost::uint16_t&                        const_reference;
00498     typedef std::size_t                                   size_type;
00499     typedef std::ptrdiff_t                                difference_type;
00500     typedef boost::uint16_t*                              iterator;
00501     typedef const boost::uint16_t*                        const_iterator;
00502     typedef std::reverse_iterator<boost::uint16_t*>       reverse_iterator;
00503     typedef std::reverse_iterator<const boost::uint16_t*> const_reverse_iterator;
00504     
00505 private:
00506     typedef vector<value_type>                            storage_type;
00507 
00508     storage_type storage_m;
00509     
00510     /*
00511         NOTE (eberdahl@adobe.com): Because c_str is required to return a null-terminated sequence,
00512         we ensure that the storage vector is always null-terminated. This means that the storage
00513         is always either empty or contains one extra character to hold the null-character.
00514      */
00515     template <typename ForwardIterator>
00516     void assign(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag)
00517     {
00518         storage_type tmp;
00519         if (first != last)
00520         {
00521             const size_type len(std::distance(first, last));
00522             tmp.reserve(len + 1);
00523             tmp.insert(tmp.end(), first, last);
00524             tmp.push_back(boost::uint16_t(0));
00525         }
00526         storage_m.swap(tmp);
00527     }
00528     
00529     template <typename InputIterator>
00530     void assign(InputIterator first, InputIterator last, std::input_iterator_tag)
00531     {
00532         storage_type tmp;
00533         if (first != last)
00534         {
00535             tmp.insert(tmp.end(), first, last);
00536             tmp.push_back(boost::uint16_t(0));
00537         }
00538         storage_m.swap(tmp);
00539     }
00540     
00541     template <typename Iterator>
00542     void assign(Iterator first, Iterator last)
00543     {
00544         assign(first, last,
00545                typename std::iterator_traits<Iterator>::iterator_category());
00546     }
00547     
00548 public:
00552     string16_t() { }
00553     
00557     string16_t(const string16_t& s) : storage_m(s.storage_m) { }
00558 
00562     string16_t(move_from<string16_t> x) : storage_m(move(x.source.storage_m)) { }
00563 
00569     string16_t(const boost::uint16_t* s);
00570 
00577     string16_t(const boost::uint16_t* s, std::size_t length);
00578     
00585     template <typename Iterator>
00586     string16_t(Iterator first, Iterator last)
00587         { assign(first, last); }
00588 
00592     ~string16_t() { }
00593     
00597     string16_t& operator=(string16_t s)
00598         { storage_m = move(s.storage_m); return *this; }
00599     
00604     const boost::uint16_t* c_str() const;
00605     
00609     void push_back(value_type c);
00610     
00614     template <typename Iterator>
00615     void append(Iterator first, Iterator last)
00616     {
00617         if (first != last)
00618         {
00619             if (!storage_m.empty())
00620                 storage_m.pop_back();
00621             
00622             storage_m.insert(storage_m.end(), first, last);
00623             storage_m.push_back(0);
00624         }
00625     }
00626     
00630     void append(const string16_t& s)
00631         { append(s.begin(), s.end()); }
00632     
00636     void append(const boost::uint16_t* s);
00637     
00641     void append(const boost::uint16_t* s, std::size_t length)
00642         { append(s, s + length); }
00643     
00647     string16_t& operator+=(const string16_t& s)
00648         { append(s); return *this; }
00649     
00653     string16_t& operator+=(const boost::uint16_t* s)
00654         { append(s); return *this; }
00655     
00659     const_iterator begin() const
00660         { return storage_m.begin(); }
00661     
00665     const_iterator end() const
00666         { return storage_m.empty() ? storage_m.end() : boost::prior(storage_m.end()); }
00667     
00671     const_reverse_iterator rbegin() const
00672         { return const_reverse_iterator(end()); }
00673     
00677     const_reverse_iterator rend() const
00678         { return const_reverse_iterator(begin()); }
00679     
00684     size_type capacity() const;
00685     
00691     void reserve(size_type n)
00692         { storage_m.reserve(0 == n ? 0 : n + 1); }
00693     
00697     void clear()
00698         { storage_m.clear(); }
00699     
00703     size_type size() const
00704         { return storage_m.empty() ? 0 : storage_m.size() - 1; }
00705     
00709     bool empty() const
00710         { return storage_m.empty(); }
00711     
00715     void swap(string16_t& s)
00716         { storage_m.swap(s.storage_m); }
00717     
00718     friend bool operator==(const string16_t& x, const string16_t& y)
00719     {
00720         return x.storage_m == y.storage_m;
00721     }
00722     
00723     friend bool operator<(const string16_t& x, const string16_t& y)
00724     {
00725         return x.storage_m < y.storage_m;
00726     }
00727     
00728     friend inline void swap(string16_t& x, string16_t& y) { x.storage_m.swap(y.storage_m); }
00729 };
00730 
00737 inline string16_t operator+(string16_t s1, const string16_t& s2)      { return move(s1 += s2); }
00738 inline string16_t operator+(string16_t s1, const boost::uint16_t* s2) { return move(s1 += s2); }
00739 
00741 
00742 /*************************************************************************************************/
00743 
00744 BOOST_STATIC_ASSERT(sizeof(string_t) == sizeof(vector<char>));
00745 BOOST_STATIC_ASSERT(sizeof(string16_t) == sizeof(vector<boost::uint16_t>));
00746 
00747 /*************************************************************************************************/
00748 
00749 } // namespace version_1
00750 
00751 /*************************************************************************************************/
00752 
00753 using version_1::string_t;
00754 using version_1::string16_t;
00755 
00756 /*************************************************************************************************/
00757 
00758 } // namespace adobe
00759 
00760 /*************************************************************************************************/
00761 
00762 ADOBE_NAME_TYPE_0("string_t:version_1:adobe", adobe::version_1::string_t)
00763 ADOBE_NAME_TYPE_0("string16_t:version_1:adobe", adobe::version_1::string16_t)
00764 
00765 ADOBE_SHORT_NAME_TYPE('s','t','r','g', adobe::version_1::string_t)
00766 ADOBE_SHORT_NAME_TYPE('s','t','1','6', adobe::version_1::string16_t)
00767 
00768 /*************************************************************************************************/
00769 
00770 namespace boost {
00771 
00772 template <>
00773 struct has_nothrow_constructor<adobe::version_1::string_t> : boost::mpl::true_ { };
00774 
00775 template <>
00776 struct has_nothrow_constructor<adobe::version_1::string16_t> : boost::mpl::true_ { };
00777 
00778 } // namespace boost
00779 
00780 /*************************************************************************************************/
00781 
00782 #endif
00783 
00784 /*************************************************************************************************/

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