Natural iterators: Examples

A part of an OpenDoc part

ODDropResult DrawEditor::Drop(Environment *ev, ODDragItemIterator* dragInfo, ODFacet* facet, ODPoint* where) { /* snipped */ // If at least one of our shapes is selected, select all of them class selection_checker : public ShapeIteratee { CSelection * selection; ODBoolean was_selected_flag; ODBoolean operation(CShape * shape) { return !(was_selected_flag = selection->IsIn(shape)); } public: selection_checker(CSelection * _selection) : selection(_selection), was_selected_flag(kODFalse) {} operator ODBoolean (void) const { return was_selected_flag; } }; selection_checker was_selected(fSelection); for_each_our_shape(was_selected); class selection_adder : public ShapeIteratee { Environment * ev; CSelection * selection; ODBoolean operation(CShape * shape) { if( !(selection->IsIn(shape)) ) selection->AddToSelection(ev, shape, kODFalse); return kODTrue; } public: selection_adder(Environment * _ev, CSelection * _selection) : ev(_ev), selection(_selection) {} }; if( was_selected ) for_each_our_shape(selection_adder(ev,fSelection)); /* snipped */ }

Note how closures are getting hold of an out-of-scope variables selection and environment

selection_adder::operation() really acts as a nested function

Moving pixels to an off-screen pixmap

Move an IMAGE to an OffScreenBuffer
ImageView::ImageView(const IMAGE& _image) : OffScreenBuffer(_image,elevation_color_CLUT_id), image(_image), viewer_pos(110,128,1<<14,0) { class ImageToPixMap : public PixelPrimAction { PixMapHandle pixmap; unsigned char * pixp; const card height, width, off_to_next_row; card curr_row, curr_col; void operation(GRAY& pixel) // put a pixel to pixmap[row,col] { *pixp++ = pixel; if( ++curr_col >= width ) curr_col = 0, curr_row++, pixp += off_to_next_row; } public: ImageToPixMap(OffScreenBuffer& buffer) : pixmap(buffer.get_pixmap()), height(buffer.height()), width(buffer.width()), off_to_next_row(buffer.bytes_per_row()-buffer.width()), curr_row(0), curr_col(0) { assert( LockPixels(pixmap) ); pixp = (unsigned char *)GetPixBaseAddr(pixmap); } ~ImageToPixMap(void) { assert( curr_row == height && curr_col == 0 ); UnlockPixels(pixmap); pixmap = 0; } }; ((IMAGE&)image).apply(ImageToPixMap(*this)); } An anonymous object ImageToPixMap: It is a closure indeed

When member function templates become widely supported by C++ compilers, I'll rewrite iterators to use them, rather than virtual functions. Then the entire iteration will be inline, _exactly_ like a for() loop, but with the benefits of simpler syntax, safety and very little set-up fuss. In my other package, I use #define'd macros to achieve the same inline effect. It's ugly, but fast: it takes only 0.6 sec on a SuperSparc 66MHz CPU to wavelet compress _and_ decompress a 512x512 8-bit grayscale image (that's a 1/4 MB of data, and the algorithm requires several passes through them)

Next | Table of contents