Re: opinion poll on text widget iterators



> 
> Hi,
> 
> I'm considering reworking tktext-port/frootkxtindex.h (in GNOME CVS).
> Advice sought, especially from language binding maintainers.
> 
> Right now I have an opaque reference-counted iterator object,
> FrooTkxtIndex. The annoying thing about this object is that 
> it sucks as an iterator. That is, if you have a loop:
> 
> FrooTkxtIndex* iter;
> iter = froo_tkxt_buffer_get_char_index(buffer, 0);
> while (iter != NULL)
> {
>   /* do stuff with iter */
> 
>   FrooTkxtIndex* freeme = iter;
>   iter = froo_tkxt_index_next_char(iter);
>   froo_tkxt_index_unref(freeme);
> }
> 
> So, yuck.
> 
> Proposed alternative is:
> 
> FrooTkxtIndex iter;
> froo_tkxt_buffer_get_char_index(buffer, 0, &iter);
> while (froo_tkxt_index_next_char(&iter))
> {
>   /* do stuff with iter */
> }

I am going to have to be different and propose that merger of
the two.  

If the api is 

void froo_tkxt_buffer_get_char_index(FrooTkxt*, int location,  FrooTkxtIter*);
#define   froo_tkxt_buffer_iter_begin(X,Y) \
  froo_tkxt_buffer_get_char_index(X,0,Y)
#define   froo_tkxt_buffer_iter_end(X,Y) \
  froo_tkxt_buffer_get_char_index(X,-1,Y)

// return false when hits end
gint froo_tkxt_buffer_iter_inc(FrooTkxtIter*);
// returns false when hits beginning
gint froo_tkxt_buffer_iter_dec(FrooTkxtIter*);
// checks to see if an iterator is the same
gint froo_tkxt_buffer_iter_comp(FrooTkxtIter*,FrooTkxtIter*)

Now for the binding I can write something like this...

 
 FrooTkxtIter iter,end;
 froo_tkxt_buffer_iter_begin(tb,iter);
 froo_tkxt_buffer_iter_end(tb,end);
 for (;froo_tkxt_buffer_iter_comp(iter,end); 
       froo_tkxt_buffer_iter_inc(iter))
   {
     /* do stuff with iter */
   }

Which binds very nicely to C++.

At the same time it allows a tight C loop like.

 FrooTkxtIter iter,end;
 froo_tkxt_buffer_iter_begin(tb,iter);
 while (froo_tkxt_buffer_iter_comp(iter,end))
   {
      /* do stuff with iter */
   }

See best of both worlds and no need for messy ref/unref and
managing a dynamic buffer.  (Wow, that is actually cool, I
wonder if we can use this to make a generic g_container) 

Here is the C++ binding of that for those interested.

  class FrooTkxt_Iter 
    {
      private: 
        FrooTkxtIter iter_;
      public:
        FrooTkxt_Iter(const FrooTkxtIter& iter) 
          { froo_tkxt_iter_copy(iter_,iter); }
        bool operator == (const FrooTkxt_Iter& iter)
          { return  froo_tkxt_iter_comp(iter_,iter);}
        bool operator != (const FrooTkxt_Iter& iter)
          { return !(*this==iter);}
        FrooTkxt_Iter& operator =(const FrooTkxt_Iter& iter)
          { froo_tkxt_iter_copy(iter_,iter); }
        FrooTkxt_Iter& operator++()  
          { froo_tkxt_iter_inc(iter_); }
        FrooTkxt_Iter& operator--()  
          { froo_tkxt_iter_dec(iter_); }
     };

or something to that effect
    
> I have some misgivings here, however. 
> 
> Misgiving #1: the static, non-refcounted object will be like 
>  GdkColor for language bindings, and may be annoying to deal 
>  with. I don't know.

Well, if done as above you can get C++ and C in one shot.
The others I am not sure about.  Likely they could use one
or the other.  (Note, that gtk-- has no problem with GdkColor
at all, but we may not be representative.)
 
> Misgiving #2: these index objects are 90% of the time not actually
>  used for iteration; it will be both easier and more efficient to use
>  _foreach() API's that are also provided for iterating over the
>  buffer. "Dereferencing" a FrooTkxtIndex is O(n) where n is the length
>  of the line containing the index. A typical use of FrooTkxtIndex is
>  more like this:

Why does it need to be O(n) the iter can have a pointer to a 
structure?  (Note, if it is O(n) don't provide it, O(n^2) 
use of this would just be too killer)

[snip]
> Misgiving #3: the static object is in some sense less opaque; the 
>  size of the struct can't be changed while retaining binary
>  compatibility, and the type can never be changed in a way 
>  that requires a destructor (can never have allocated memory as 
>  part of the iterator, basically).

That shouldn't really be too big of deal.  You can make the
darn thing large with plenty of expansion area and then change
its size between major versions.

--Karl



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]