Back to index

lightning-sunbird  0.9+nobinonly
nsStringIterator.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Scott Collins <scc@mozilla.org> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #ifndef nsStringIterator_h___
00040 #define nsStringIterator_h___
00041 
00042 #ifndef nsCharTraits_h___
00043 #include "nsCharTraits.h"
00044 #endif
00045 
00046 #ifndef nsAlgorithm_h___
00047 #include "nsAlgorithm.h"
00048 #endif
00049 
00050 #ifndef nsDebug_h___
00051 #include "nsDebug.h"
00052 #endif
00053 
00058 template <class CharT>
00059 class nsReadingIterator
00060   {
00061     public:
00062       typedef nsReadingIterator<CharT>    self_type;
00063       typedef ptrdiff_t                   difference_type;
00064       typedef CharT                       value_type;
00065       typedef const CharT*                pointer;
00066       typedef const CharT&                reference;
00067 
00068     private:
00069       friend class nsAString;
00070       friend class nsACString;
00071 #ifdef MOZ_V1_STRING_ABI
00072       friend class nsSubstring;
00073       friend class nsCSubstring;
00074 #endif
00075 
00076         // unfortunately, the API for nsReadingIterator requires that the
00077         // iterator know its start and end positions.  this was needed when
00078         // we supported multi-fragment strings, but now it is really just
00079         // extra baggage.  we should remove mStart and mEnd at some point.
00080 
00081       const CharT* mStart;
00082       const CharT* mEnd;
00083       const CharT* mPosition;
00084 
00085     public:
00086       nsReadingIterator() { }
00087       // nsReadingIterator( const nsReadingIterator<CharT>& );                    // auto-generated copy-constructor OK
00088       // nsReadingIterator<CharT>& operator=( const nsReadingIterator<CharT>& );  // auto-generated copy-assignment operator OK
00089 
00090       inline void normalize_forward() {}
00091       inline void normalize_backward() {}
00092 
00093       pointer
00094       start() const
00095         {
00096           return mStart;
00097         }
00098 
00099       pointer
00100       end() const
00101         {
00102           return mEnd;
00103         }
00104 
00105       pointer
00106       get() const
00107         {
00108           return mPosition;
00109         }
00110       
00111       CharT
00112       operator*() const
00113         {
00114           return *get();
00115         }
00116 
00117 #if 0
00118         // An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
00119         //  don't like this when |CharT| is a type without members.
00120       pointer
00121       operator->() const
00122         {
00123           return get();
00124         }
00125 #endif
00126 
00127       self_type&
00128       operator++()
00129         {
00130           ++mPosition;
00131           return *this;
00132         }
00133 
00134       self_type
00135       operator++( int )
00136         {
00137           self_type result(*this);
00138           ++mPosition;
00139           return result;
00140         }
00141 
00142       self_type&
00143       operator--()
00144         {
00145           --mPosition;
00146           return *this;
00147         }
00148 
00149       self_type
00150       operator--( int )
00151         {
00152           self_type result(*this);
00153           --mPosition;
00154           return result;
00155         }
00156 
00157       difference_type
00158       size_forward() const
00159         {
00160           return mEnd - mPosition;
00161         }
00162 
00163       difference_type
00164       size_backward() const
00165         {
00166           return mPosition - mStart;
00167         }
00168 
00169       self_type&
00170       advance( difference_type n )
00171         {
00172           if (n > 0)
00173             {
00174               difference_type step = NS_MIN(n, size_forward());
00175 
00176               NS_ASSERTION(step>0, "can't advance a reading iterator beyond the end of a string");
00177 
00178               mPosition += step;
00179             }
00180           else if (n < 0)
00181             {
00182               difference_type step = NS_MAX(n, -size_backward());
00183 
00184               NS_ASSERTION(step<0, "can't advance (backward) a reading iterator beyond the end of a string");
00185 
00186               mPosition += step;
00187             }
00188           return *this;
00189         }
00190   };
00191 
00196 template <class CharT>
00197 class nsWritingIterator
00198   {
00199     public:
00200       typedef nsWritingIterator<CharT>   self_type;
00201       typedef ptrdiff_t                  difference_type;
00202       typedef CharT                      value_type;
00203       typedef CharT*                     pointer;
00204       typedef CharT&                     reference;
00205 
00206     private:
00207       friend class nsAString;
00208       friend class nsACString;
00209 #ifdef MOZ_V1_STRING_ABI
00210       friend class nsSubstring;
00211       friend class nsCSubstring;
00212 #endif
00213 
00214         // unfortunately, the API for nsWritingIterator requires that the
00215         // iterator know its start and end positions.  this was needed when
00216         // we supported multi-fragment strings, but now it is really just
00217         // extra baggage.  we should remove mStart and mEnd at some point.
00218 
00219       CharT* mStart;
00220       CharT* mEnd;
00221       CharT* mPosition;
00222 
00223     public:
00224       nsWritingIterator() { }
00225       // nsWritingIterator( const nsWritingIterator<CharT>& );                    // auto-generated copy-constructor OK
00226       // nsWritingIterator<CharT>& operator=( const nsWritingIterator<CharT>& );  // auto-generated copy-assignment operator OK
00227 
00228       inline void normalize_forward() {}
00229       inline void normalize_backward() {}
00230 
00231       pointer
00232       start() const
00233         {
00234           return mStart;
00235         }
00236 
00237       pointer
00238       end() const
00239         {
00240           return mEnd;
00241         }
00242 
00243       pointer
00244       get() const
00245         {
00246           return mPosition;
00247         }
00248       
00249       reference
00250       operator*() const
00251         {
00252           return *get();
00253         }
00254 
00255 #if 0
00256         // An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
00257         //  don't like this when |CharT| is a type without members.
00258       pointer
00259       operator->() const
00260         {
00261           return get();
00262         }
00263 #endif
00264 
00265       self_type&
00266       operator++()
00267         {
00268           ++mPosition;
00269           return *this;
00270         }
00271 
00272       self_type
00273       operator++( int )
00274         {
00275           self_type result(*this);
00276           ++mPosition;
00277           return result;
00278         }
00279 
00280       self_type&
00281       operator--()
00282         {
00283           --mPosition;
00284           return *this;
00285         }
00286 
00287       self_type
00288       operator--( int )
00289         {
00290           self_type result(*this);
00291           --mPosition;
00292           return result;
00293         }
00294 
00295       difference_type
00296       size_forward() const
00297         {
00298           return mEnd - mPosition;
00299         }
00300 
00301       difference_type
00302       size_backward() const
00303         {
00304           return mPosition - mStart;
00305         }
00306 
00307       self_type&
00308       advance( difference_type n )
00309         {
00310           if (n > 0)
00311             {
00312               difference_type step = NS_MIN(n, size_forward());
00313 
00314               NS_ASSERTION(step>0, "can't advance a writing iterator beyond the end of a string");
00315 
00316               mPosition += step;
00317             }
00318           else if (n < 0)
00319             {
00320               difference_type step = NS_MAX(n, -size_backward());
00321 
00322               NS_ASSERTION(step<0, "can't advance (backward) a writing iterator beyond the end of a string");
00323 
00324               mPosition += step;
00325             }
00326           return *this;
00327         }
00328 
00329       PRUint32
00330       write( const value_type* s, PRUint32 n )
00331         {
00332           NS_ASSERTION(size_forward() > 0, "You can't |write| into an |nsWritingIterator| with no space!");
00333 
00334           nsCharTraits<value_type>::move(mPosition, s, n);
00335           advance( difference_type(n) );
00336           return n;
00337         }
00338   };
00339 
00340 template <class CharT>
00341 inline
00342 PRBool
00343 operator==( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
00344   {
00345     return lhs.get() == rhs.get();
00346   }
00347 
00348 template <class CharT>
00349 inline
00350 PRBool
00351 operator!=( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
00352   {
00353     return lhs.get() != rhs.get();
00354   }
00355 
00356 
00357   //
00358   // |nsWritingIterator|s
00359   //
00360 
00361 template <class CharT>
00362 inline
00363 PRBool
00364 operator==( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
00365   {
00366     return lhs.get() == rhs.get();
00367   }
00368 
00369 template <class CharT>
00370 inline
00371 PRBool
00372 operator!=( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
00373   {
00374     return lhs.get() != rhs.get();
00375   }
00376 
00377 #endif /* !defined(nsStringIterator_h___) */