Skip to content

Commit 1c4f77e

Browse files
Completing ChannelList Iterator API (#2384)
* Added additional operator overloads '--', '*' and '->' for ChannelList::Iterator and ChannelList::ConstIterator. Also added global operator overloads '==' and '!=' for Iterator class. (issue #1325) Signed-off-by: Aries Moczar <arcmantis@protulae.com> * Added '==' and '!=' overloads for mixed Iterator and ConstIterator comparisons. Added Iterator and ConstIterator traits. Signed-off-by: Aries Moczar <arcmantis@protulae.com> * Added test to testChannels unit-test to verify functionality of ChannelList::Iterator/ConstIterator Signed-off-by: Aries Moczar <arcmantis@protulae.com> --------- Signed-off-by: Aries Moczar <arcmantis@protulae.com> Co-authored-by: Cary Phillips <cary@ilm.com>
1 parent 2ec8eb9 commit 1c4f77e

2 files changed

Lines changed: 217 additions & 5 deletions

File tree

src/lib/OpenEXR/ImfChannelList.h

Lines changed: 148 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,12 @@ class IMF_EXPORT_TYPE ChannelList
254254
class IMF_EXPORT_TYPE ChannelList::Iterator
255255
{
256256
public:
257+
using iterator_category = std::bidirectional_iterator_tag;
258+
using value_type = Channel;
259+
using difference_type = std::ptrdiff_t;
260+
using pointer = Channel*;
261+
using reference = Channel&;
262+
257263
IMF_EXPORT
258264
Iterator ();
259265
IMF_EXPORT
@@ -264,20 +270,45 @@ class IMF_EXPORT_TYPE ChannelList::Iterator
264270
IMF_EXPORT
265271
Iterator operator++ (int);
266272

273+
IMF_EXPORT
274+
Iterator& operator-- ();
275+
IMF_EXPORT
276+
Iterator operator-- (int);
277+
278+
IMF_EXPORT
279+
reference operator* () const;
280+
281+
IMF_EXPORT
282+
pointer operator-> () const;
283+
267284
IMF_EXPORT
268285
const char* name () const;
269286
IMF_EXPORT
270-
Channel& channel () const;
287+
reference channel () const;
271288

272289
private:
273290
friend class ChannelList::ConstIterator;
274291

292+
friend bool operator== (Iterator&, Iterator&);
293+
friend bool operator== (Iterator&, const ConstIterator&);
294+
friend bool operator== (const ConstIterator&, Iterator&);
295+
296+
friend bool operator!= (Iterator&, Iterator&);
297+
friend bool operator!= (Iterator&, const ConstIterator&);
298+
friend bool operator!= (const ConstIterator&, Iterator&);
299+
275300
ChannelList::ChannelMap::iterator _i;
276301
};
277302

278303
class IMF_EXPORT_TYPE ChannelList::ConstIterator
279304
{
280305
public:
306+
using iterator_category = std::bidirectional_iterator_tag;
307+
using value_type = Channel;
308+
using difference_type = std::ptrdiff_t;
309+
using pointer = const Channel*;
310+
using reference = const Channel&;
311+
281312
IMF_EXPORT
282313
ConstIterator ();
283314
IMF_EXPORT
@@ -290,14 +321,30 @@ class IMF_EXPORT_TYPE ChannelList::ConstIterator
290321
IMF_EXPORT
291322
ConstIterator operator++ (int);
292323

324+
IMF_EXPORT
325+
ConstIterator& operator-- ();
326+
IMF_EXPORT
327+
ConstIterator operator-- (int);
328+
329+
IMF_EXPORT
330+
reference operator* () const;
331+
332+
IMF_EXPORT
333+
pointer operator-> () const;
334+
293335
IMF_EXPORT
294336
const char* name () const;
295337
IMF_EXPORT
296-
const Channel& channel () const;
338+
reference channel () const;
297339

298340
private:
299341
friend bool operator== (const ConstIterator&, const ConstIterator&);
342+
friend bool operator== (Iterator&, const ConstIterator&);
343+
friend bool operator== (const ConstIterator&, Iterator&);
344+
300345
friend bool operator!= (const ConstIterator&, const ConstIterator&);
346+
friend bool operator!= (Iterator&, const ConstIterator&);
347+
friend bool operator!= (const ConstIterator&, Iterator&);
301348

302349
ChannelList::ChannelMap::const_iterator _i;
303350
};
@@ -333,13 +380,40 @@ ChannelList::Iterator::operator++ (int)
333380
return tmp;
334381
}
335382

383+
inline ChannelList::Iterator&
384+
ChannelList::Iterator::operator-- ()
385+
{
386+
--_i;
387+
return *this;
388+
}
389+
390+
inline ChannelList::Iterator
391+
ChannelList::Iterator::operator-- (int)
392+
{
393+
Iterator tmp = *this;
394+
--_i;
395+
return tmp;
396+
}
397+
398+
inline ChannelList::Iterator::reference
399+
ChannelList::Iterator::operator* () const
400+
{
401+
return _i->second;
402+
}
403+
404+
inline ChannelList::Iterator::pointer
405+
ChannelList::Iterator::operator-> () const
406+
{
407+
return &_i->second;
408+
}
409+
336410
inline const char*
337411
ChannelList::Iterator::name () const
338412
{
339413
return *_i->first;
340414
}
341415

342-
inline Channel&
416+
inline ChannelList::Iterator::reference
343417
ChannelList::Iterator::channel () const
344418
{
345419
return _i->second;
@@ -379,30 +453,99 @@ ChannelList::ConstIterator::operator++ (int)
379453
return tmp;
380454
}
381455

456+
inline ChannelList::ConstIterator&
457+
ChannelList::ConstIterator::operator-- ()
458+
{
459+
--_i;
460+
return *this;
461+
}
462+
463+
inline ChannelList::ConstIterator
464+
ChannelList::ConstIterator::operator-- (int)
465+
{
466+
ConstIterator tmp = *this;
467+
--_i;
468+
return tmp;
469+
}
470+
471+
inline ChannelList::ConstIterator::reference
472+
ChannelList::ConstIterator::operator* () const
473+
{
474+
return _i->second;
475+
}
476+
477+
inline ChannelList::ConstIterator::pointer
478+
ChannelList::ConstIterator::operator-> () const
479+
{
480+
return &_i->second;
481+
}
482+
382483
inline const char*
383484
ChannelList::ConstIterator::name () const
384485
{
385486
return *_i->first;
386487
}
387488

388-
inline const Channel&
489+
inline ChannelList::ConstIterator::reference
389490
ChannelList::ConstIterator::channel () const
390491
{
391492
return _i->second;
392493
}
393494

495+
inline bool
496+
operator== (
497+
ChannelList::Iterator& x, ChannelList::Iterator& y)
498+
{
499+
return x._i == y._i;
500+
}
501+
394502
inline bool
395503
operator== (
396504
const ChannelList::ConstIterator& x, const ChannelList::ConstIterator& y)
397505
{
398506
return x._i == y._i;
399507
}
400508

509+
inline bool
510+
operator== (
511+
ChannelList::Iterator& x, const ChannelList::ConstIterator& y)
512+
{
513+
return x._i == y._i;
514+
}
515+
516+
inline bool
517+
operator== (
518+
const ChannelList::ConstIterator& x, ChannelList::Iterator& y)
519+
{
520+
return x._i == y._i;
521+
}
522+
523+
inline bool
524+
operator!= (
525+
ChannelList::Iterator& x, ChannelList::Iterator& y)
526+
{
527+
return !(x._i == y._i);
528+
}
529+
401530
inline bool
402531
operator!= (
403532
const ChannelList::ConstIterator& x, const ChannelList::ConstIterator& y)
404533
{
405-
return !(x == y);
534+
return !(x._i == y._i);
535+
}
536+
537+
inline bool
538+
operator!= (
539+
ChannelList::Iterator& x, const ChannelList::ConstIterator& y)
540+
{
541+
return !(x._i == y._i);
542+
}
543+
544+
inline bool
545+
operator!= (
546+
const ChannelList::ConstIterator& x, ChannelList::Iterator& y)
547+
{
548+
return !(x._i == y._i);
406549
}
407550

408551
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT

src/test/OpenEXRTest/testChannels.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,82 @@ writeRead (
218218
cout << endl;
219219
}
220220

221+
void
222+
verifyIterators(void)
223+
{
224+
ChannelList l1;
225+
226+
l1.insert("A", Channel(HALF));
227+
l1.insert("B", Channel(HALF));
228+
l1.insert("C", Channel(HALF));
229+
230+
ChannelList::Iterator it1 = l1.begin();
231+
ChannelList::ConstIterator cit1 = l1.begin();
232+
233+
ChannelList::Iterator it2 = l1.end();
234+
ChannelList::ConstIterator cit2 = l1.end();
235+
236+
// Test global '!=' overloads
237+
assert(it1 != it2);
238+
assert(it1 != cit2);
239+
assert(cit1 != it2);
240+
assert(cit1 != cit2);
241+
242+
// Test global '==' overloads
243+
assert(it1 == it1);
244+
assert(it1 == cit1);
245+
assert(cit1 == it1);
246+
assert(cit1 == cit1);
247+
248+
// Test post/pre '++' overloads
249+
it1++;
250+
++it1;
251+
cit1++;
252+
++cit1;
253+
254+
// Test post/pre '--' overloads
255+
it1--;
256+
--it1;
257+
cit1--;
258+
--cit1;
259+
260+
assert(it1 == l1.begin());
261+
assert(cit1 == l1.begin());
262+
263+
while (it1 != l1.end())
264+
{
265+
266+
// Test '*' overloads
267+
Channel& c = *it1;
268+
const Channel& cc = *cit1;
269+
assert(c.type == HALF);
270+
assert(cc.type == HALF);
271+
272+
// Test '->' overload
273+
assert(it1->type == HALF);
274+
assert(cit1->type == HALF);
275+
276+
// Test pre/post '++' overloads
277+
it1++;
278+
cit1++;
279+
280+
}
281+
282+
assert(it1 == l1.end());
283+
assert(cit1 == l1.end());
284+
}
285+
221286
} // namespace
222287

223288
void
224289
testChannels (const std::string& tempDir)
225290
{
226291
try
227292
{
293+
cout << "Testing ChannelList Iterator behavior" << endl;
294+
295+
verifyIterators ();
296+
228297
cout << "Testing filling of missing channels" << endl;
229298

230299
const int W = 117;

0 commit comments

Comments
 (0)