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     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 /*************************************************************************************************/

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