list.h

Go to the documentation of this file.
00001 
00005 
00006 //
00007 // Copyright (c) 2001-2004 California Institute of Technology
00008 // Copyright (c) 2004-2007 University of Southern California
00009 // Rob Peters <rjpeters at usc dot edu>
00010 //
00011 // created: Wed Jul 11 12:00:17 2001
00012 // commit: $Id: list.h 10065 2007-04-12 05:54:56Z rjpeters $
00013 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/tcl/list.h $
00014 //
00015 // --------------------------------------------------------------------
00016 //
00017 // This file is part of GroovX.
00018 //   [http://ilab.usc.edu/rjpeters/groovx/]
00019 //
00020 // GroovX is free software; you can redistribute it and/or modify it
00021 // under the terms of the GNU General Public License as published by
00022 // the Free Software Foundation; either version 2 of the License, or
00023 // (at your option) any later version.
00024 //
00025 // GroovX is distributed in the hope that it will be useful, but
00026 // WITHOUT ANY WARRANTY; without even the implied warranty of
00027 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00028 // General Public License for more details.
00029 //
00030 // You should have received a copy of the GNU General Public License
00031 // along with GroovX; if not, write to the Free Software Foundation,
00032 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00033 //
00035 
00036 #ifndef GROOVX_TCL_LIST_H_UTC20050628162420_DEFINED
00037 #define GROOVX_TCL_LIST_H_UTC20050628162420_DEFINED
00038 
00039 #include "tcl/conversions.h"
00040 #include "tcl/obj.h"
00041 
00042 #include "rutz/shared_ptr.h"
00043 
00044 namespace tcl
00045 {
00046   class list;
00047 
00048   tcl::list aux_convert_to(Tcl_Obj* obj, tcl::list*);
00049   tcl::obj aux_convert_from(tcl::list list_value);
00050 }
00051 
00053 
00058 
00059 
00060 class tcl::list
00061 {
00062 public:
00064   list();
00065 
00066   list(const tcl::obj& x);
00067 
00068   list(const list& other) :
00069     m_list_obj(other.m_list_obj),
00070     m_elements(other.m_elements),
00071     m_length(other.m_length)
00072   {}
00073 
00074   list& operator=(const list& other)
00075   {
00076     m_list_obj = other.m_list_obj;
00077     m_elements = other.m_elements;
00078     m_length = other.m_length;
00079     return *this;
00080   }
00081 
00082   tcl::obj as_obj() const { return m_list_obj; }
00083 
00085   Tcl_Obj* at(unsigned int index) const;
00086 
00088   Tcl_Obj* operator[](unsigned int index) const
00089     {
00090       update(); return m_elements[index];
00091     }
00092 
00093   Tcl_Obj* const* elements() const
00094     {
00095       update(); return m_elements;
00096     }
00097 
00098   template <class T>
00099   inline T get(unsigned int index, T* /*dummy*/=0) const;
00100 
00101   unsigned int size() const { update(); return m_length; }
00102   unsigned int length() const { update(); return m_length; }
00103 
00104   template <class T>
00105   void append(T t) { do_append(tcl::convert_from(t), 1); }
00106 
00107   template <class T>
00108   void append(T t, unsigned int times)
00109     {
00110       do_append(tcl::convert_from(t), times);
00111     }
00112 
00113   template <class Itr>
00114   void append_range(Itr itr, Itr end)
00115     {
00116       while (itr != end)
00117         {
00118           append(*itr);
00119           ++itr;
00120         }
00121     }
00122 
00123   class iterator_base;
00124   template <class T> class iterator;
00125 
00126   template <class T>
00127   iterator<T> begin(T* /*dummy*/=0);
00128 
00129   template <class T>
00130   iterator<T> end(T* /*dummy*/=0);
00131 
00133   class appender
00134   {
00135     tcl::list& m_list_obj;
00136   public:
00137     appender(tcl::list& x) : m_list_obj(x) {}
00138 
00139     template <class T>
00140     appender& operator=(const T& val)
00141     { m_list_obj.append(val); return *this; }
00142 
00143     appender& operator*() { return *this; }
00144     appender& operator++() { return *this; }
00145     appender operator++(int) { return *this; }
00146   };
00147 
00148   appender back_appender() { return appender(*this); }
00149 
00151   static unsigned int get_obj_list_length(Tcl_Obj* obj);
00152 
00153 private:
00154   void do_append(const tcl::obj& obj, unsigned int times);
00155 
00156   void update() const
00157     {
00158       if (m_elements==0)
00159         split();
00160     }
00161 
00162   void split() const;
00163 
00164   void invalidate() { m_elements = 0; m_length = 0; }
00165 
00166   mutable tcl::obj      m_list_obj;
00167   mutable Tcl_Obj**     m_elements;
00168   mutable unsigned int  m_length;
00169 };
00170 
00171 
00173 
00178 
00179 
00180 class tcl::list::iterator_base
00181 {
00182 protected:
00183   // Make protected to prevent people from instantiating iterator_base directly.
00184   ~iterator_base() {}
00185 
00186 public:
00187   typedef int difference_type;
00188 
00189   enum position { BEGIN, END };
00190 
00191   iterator_base(const list& owner, position start_pos = BEGIN) :
00192     m_list_obj(owner),
00193     m_index(start_pos == BEGIN ? 0 : owner.length())
00194   {}
00195 
00196   iterator_base(Tcl_Obj* x, position start_pos = BEGIN) :
00197     m_list_obj(x),
00198     m_index(start_pos == BEGIN ? 0 : m_list_obj.length())
00199   {}
00200 
00201   // default copy-constructor, assignment operator OK
00202 
00203   iterator_base& operator++()
00204     { ++m_index; return *this; }
00205 
00206   iterator_base operator++(int)
00207     { iterator_base temp(*this); ++m_index; return temp; }
00208 
00209   difference_type operator-(const iterator_base& other) const
00210     {
00211       if (this->m_index > other.m_index)
00212         return int(this->m_index - other.m_index);
00213       else
00214         return -(int(other.m_index - this->m_index));
00215     }
00216 
00217   bool operator==(const iterator_base& other) const
00218     { return m_index == other.m_index; }
00219 
00220   bool operator!=(const iterator_base& other) const
00221     { return !operator==(other); }
00222 
00223   bool is_valid() const
00224     { return m_index < m_list_obj.length(); }
00225 
00226   bool has_more() const
00227     { return m_index < (m_list_obj.length()-1); }
00228 
00229   bool nelems() const
00230     { return m_list_obj.length(); }
00231 
00232 protected:
00233   Tcl_Obj* current() const
00234     { return m_list_obj.at(m_index); }
00235 
00236 private:
00237   list m_list_obj;
00238   unsigned int m_index;
00239 
00240 };
00241 
00242 
00244 
00251 
00252 
00253 template <class T>
00254 class tcl::list::iterator : public tcl::list::iterator_base
00255 {
00256   // Keep a copy of the current value here so that operator*() can
00257   // return a reference rather than by value.
00258   mutable rutz::shared_ptr<const T> m_current;
00259 
00260 public:
00261   iterator(const list& owner, position start_pos = BEGIN) :
00262     iterator_base(owner, start_pos), m_current() {}
00263 
00264   iterator(Tcl_Obj* x, position start_pos = BEGIN) :
00265     iterator_base(x, start_pos), m_current() {}
00266 
00267   typedef T value_type;
00268 
00269   const T& operator*() const
00270   {
00271     m_current.reset(new T(tcl::convert_to<T>(current())));
00272     return *m_current;
00273   }
00274 };
00275 
00276 
00278 //
00279 // Inline member definitions
00280 //
00282 
00283 #include "tcl/conversions.h"
00284 
00285 template <class T>
00286 inline T tcl::list::get(unsigned int index, T* /*dummy*/) const
00287 {
00288   return tcl::convert_to<T>(at(index));
00289 }
00290 
00291 template <class T>
00292 inline tcl::list::iterator<T> tcl::list::begin(T* /*dummy*/)
00293 {
00294   return iterator<T>(*this, iterator_base::BEGIN);
00295 }
00296 
00297 template <class T>
00298 inline tcl::list::iterator<T> tcl::list::end(T* /*dummy*/)
00299 {
00300   return iterator<T>(*this, iterator_base::END);
00301 }
00302 
00303 static const char __attribute__((used)) vcid_groovx_tcl_list_h_utc20050628162420[] = "$Id: list.h 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00304 #endif // !GROOVX_TCL_LIST_H_UTC20050628162420_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:41 2008 by Doxygen version 1.5.5.