Results 1 to 9 of 9

Thread: QDirIterator internals?

  1. #1
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default QDirIterator internals?

    Hi all,

    I have a thin wrapper around QDirIterator. This wrapper should be "filterable" by an internal regular expression.

    Out-of-the-box QDirIterator supports globbing but not regexes. Also, from the doc
    QDirIterator is uni-directional (i.e., you cannot iterate directories in reverse order) and does not allow random access
    so I cannot simply set a savepoint, then iterate+skip, and finally revert to the savepoint.
    Finally, QDirIterator doesn't provide a copy ctor or clone either.

    Question:
    Is a QDirIterator's order guaranteed? In other words: Is it safe to simulate a copy ctor by creating a new QDirIterator from the original one's path(), then advance it until its filePath() matches the original one's?

    Or is there another solution to my problem? Thx for your consideration.


    PS: I'm on 5.1. Mind that the QTCLASS link above links to 4.8, though on first sight there are no differences.

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QDirIterator internals?

    I haven't had a look at the code but my understanding is that it uses the platform's directory traversing API.

    So creating a new QDirIterator will call into that API again. If anything has changed the new iterator might have a different iteration result sequence than the first one.

    However I don't see why you would need to go back for your use case of filtering using regular expression.
    Your iterator will call into the ecapsulated iterator untill your criteria is met and then return this data until it is moved forward, no?

    Cheers,
    _

  3. #3
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QDirIterator internals?

    Hi and thx,

    Quote Originally Posted by anda_skoa View Post
    I haven't had a look at the code but my understanding is that it uses the platform's directory traversing API.
    I had a short glimpse but refrained from getting into the code for complexity.

    Quote Originally Posted by anda_skoa View Post
    So creating a new QDirIterator will call into that API again. If anything has changed the new iterator might have a different iteration result sequence than the first one.
    If your understanding is correct, then these changes would apply to the "original" iterator as well, wouldn't they? In other words: Unbuffered iterators are always invalidated if the underlying collection changes, aren't they?
    Edit:
    As long as the order of paths QDirIterator returns is invariant, proceeding to the same filePath() should "sync" the iterators. Of course I'd miss changes up to this path, but the same would be true for the original iterator. Or so I think

    Quote Originally Posted by anda_skoa View Post
    However I don't see why you would need to go back for your use case of filtering using regular expression.
    Your iterator will call into the ecapsulated iterator untill your criteria is met and then return this data until it is moved forward, no?
    The encapsulated iterator doesn't support regexes. I'd have to do this myself and query hasNext() multiple times to skip unmatched iterator states. This would require to call next() in turns, thus altering the iterator's state, which hasNext() shouldn't do.

    Do I overlook anything?
    Last edited by zaphod.b; 4th December 2013 at 17:34.

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QDirIterator internals?

    Quote Originally Posted by zaphod.b View Post
    The encapsulated iterator doesn't support regexes. I'd have to do this myself and query hasNext() multiple times to skip unmatched iterator states. This would require to call next() in turns, thus altering the iterator's state, which hasNext() shouldn't do.

    Do I overlook anything?
    Maybe I misunderstood what you are trying to do then. My interpretation was that you wanted to iterate over a directory and only get files which match a certain regular expression.
    Bascially iterating over a "view" on the directory based on the regex.

    Cheers,
    _

  5. #5
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QDirIterator internals?

    Quote Originally Posted by anda_skoa View Post
    Maybe I misunderstood what you are trying to do then. My interpretation was that you wanted to iterate over a directory and only get files which match a certain regular expression.
    Bascially iterating over a "view" on the directory based on the regex.
    You've got me right. I still don't see how this is trivial however...

    Could you please elaborate on how you would solve this task? In particular I don't see how to implement hasNext() such that it skips items returned by QDirIterator::hasNext() that are unmatched by the regex? Unless there's a way to restore QDirIterator's state somehow, that is...

    Thx for taking the trouble!

  6. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QDirIterator internals?

    Basically you have the next match already retrieved from the QDirIterator at all times
    Pseudo code:
    Qt Code:
    1. class RegExIterator
    2. {
    3. public:
    4. RegExIterator(Dir, RegEx)
    5.  
    6. bool hasNext();
    7. QFileInfo next();
    8.  
    9. private:
    10. RegEx regex;
    11. QDirIterator dirIt;
    12. QFileInfo nextMatch;
    13.  
    14. void findNext();
    15. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. RegExIterator(...)
    2. // store params in members
    3. // init QDirIterator member
    4. {
    5. findNext():
    6. }
    7.  
    8. bool hasNext()
    9. {
    10. return nextMatch != QFileInfo();
    11. }
    12.  
    13. QFileInfo next()
    14. {
    15. QFileInfo result = nextMatch;
    16.  
    17. findNext();
    18.  
    19. return result;
    20. }
    21.  
    22. void findNext()
    23. {
    24. // iterate over dirIt until match found
    25. // store in nextMatch
    26. }
    To copy to clipboard, switch view to plain text mode 

    Cheers,
    _

  7. #7
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QDirIterator internals?

    Thx, but sorry, I don't think this solves the problem.

    Quote Originally Posted by anda_skoa View Post
    Basically you have the next match already retrieved from the QDirIterator at all times
    Is that so? I think not.

    Edit:
    Ah, I think I can follow your train of thoughts at last!
    Do you say you are ok with hasNext() altering dirIt's state, and have next() only return this altered state rather than advance dirIt itself?
    This will break if next() is called without hasNext(). I'd not want to do this.


    Unfortunately your pseudo code spares the relevant part:
    Quote Originally Posted by anda_skoa View Post
    Qt Code:
    1. void findNext()
    2. {
    3. // iterate over dirIt until match found
    4. // store in nextMatch
    5. }
    To copy to clipboard, switch view to plain text mode 
    How exactly do you do this?
    "Iterate over dirIt" generally implies calling QDirIterator::hasNext() and QDirIterator::next() (for the regex match) in turns, the latter changing the iterator's state.
    "Until match found" generally implies to run these cycles more than once unless the very first item returned by QDirIterator matches.

    Also in your pseudo code hasNext() would have to call findNext(), too.

    Let me try to clarify.
    The general pseudo code for the caller using your syntax is
    Qt Code:
    1. RegExIterator rxIt(dir, rx);
    2. while ( rxIt.hasNext() ) {
    3. QFileInfo fi = rxIt.next();
    4. //do something with fi
    5. }
    To copy to clipboard, switch view to plain text mode 
    Now consider this directory structure
    Qt Code:
    1. dir/
    2. a
    3. x
    4. aa
    5. y
    To copy to clipboard, switch view to plain text mode 
    and assume a regex of "a+". The expexted matches are {a, aa}, while {x, y} shall be skipped by the iterator.
    Further assume the iterator's position (= state) to be aa. Expected result of hasNext() is false, and next() shall return an invalid result.
    The hasNext() algorithm steps would be (loop serialized for clarity)
    Qt Code:
    1. call dirIt.hasNext() //true
    2. call dirIt.next() //necessary to (1)match regex, (2)prepare for 2nd hasNext(). This alters dirIt's position to y!
    3. call dirIt.hasNext() again //false
    4. revert dirIt position to aa //hasNext() must not alter state!
    To copy to clipboard, switch view to plain text mode 
    Now, given QDirIterator's limitations I listed in this thread's first post, if I could perform the above algorithm on a dirIt copy, it would not change the original dirIt's state and I'd be safe.
    In the above example, inside hasNext() I'd create another QDirIterator based on dir/, advance it to aa, then perform the algorithm on the "copy". Obviously this would only work if dirIt and copyDirIt return the items in the same order.
    Last edited by zaphod.b; 5th December 2013 at 16:26.

  8. #8
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QDirIterator internals?

    Quote Originally Posted by zaphod.b View Post
    Do you say you are ok with hasNext() altering dirIt's state, and have next() only return this altered state rather than advance dirIt itself?
    This will break if next() is called without hasNext(). I'd not want to do this.
    No. Only next() alters the state, hasNext() does not. It only returns the value of a comparison, it does not call findNext().

    Quote Originally Posted by zaphod.b View Post
    Unfortunately your pseudo code spares the relevant part:

    How exactly do you do this?
    "Iterate over dirIt" generally implies calling QDirIterator::hasNext() and QDirIterator::next() (for the regex match) in turns, the latter changing the iterator's state.
    "Until match found" generally implies to run these cycles more than once unless the very first item returned by QDirIterator matches.
    Exactly.

    Qt Code:
    1. void findNext()
    2. {
    3. while ( dirIt.hasNext() ) {
    4. QString file = dirIt.next();
    5. if ( regexp.match( file ) ) {
    6. nextMatch = dirIt.fileInfo();
    7. return;
    8. }
    9. }
    10.  
    11. nextMatch = QFileInfo();
    12. }
    To copy to clipboard, switch view to plain text mode 
    You could also just keep the string instead of the file info.

    Quote Originally Posted by zaphod.b View Post
    Also in your pseudo code hasNext() would have to call findNext(), too.
    No, only next() and the constructor do.

    Quote Originally Posted by zaphod.b View Post
    Let me try to clarify.
    The general pseudo code for the caller using your syntax is
    Qt Code:
    1. RegExIterator rxIt(dir, rx);
    2. while ( rxIt.hasNext() ) {
    3. QFileInfo fi = rxIt.next();
    4. //do something with fi
    5. }
    To copy to clipboard, switch view to plain text mode 
    Now consider this directory structure
    Qt Code:
    1. dir/
    2. a
    3. x
    4. aa
    5. y
    To copy to clipboard, switch view to plain text mode 
    and assume a regex of "a+". The expexted matches are {a, aa}, while {x, y} shall be skipped by the iterator.
    The call sequence for that would be like this:
    Qt Code:
    1. RegExItterator constructor
    2. QDirIterator constructor
    3. findNext
    4. dirIt.hasNext -> true
    5. dirIt.next -> "a"
    6. nextMatch -> "a"
    7.  
    8. RegExIterator.hasNext
    9. nextMatch valid -> true
    10.  
    11. RegExIterator.next
    12. result = "a"
    13. findNext
    14. dirIt.hasNext -> true
    15. dirIt.next -> "x" (no match, loop continues)
    16. dirIt.hasNext -> true
    17. dirIt.next -> "aa"
    18. nextMatch -> "aa"
    19. return result
    20.  
    21. RegExIterator.hasNext
    22. nextMatch valid -> true
    23.  
    24. RegExIterator.next
    25. result = "aa"
    26. findNext
    27. dirIt.hasNext -> true
    28. dirIt.next -> "y" (no match, loop continues)
    29. dirIt.hasNext -> false
    30. nextMatch -> reset/clear
    31. return result
    32.  
    33. RegExIterator.hasNext
    34. nextMatch invalid -> false
    To copy to clipboard, switch view to plain text mode 

    Cheers,
    _

  9. The following user says thank you to anda_skoa for this useful post:

    zaphod.b (6th December 2013)

  10. #9
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QDirIterator internals?

    Oh my... This is trivial indeed.
    Sometimes you just don't see the wood for the trees. I was afraid that was the case here, and it was...

    Quote Originally Posted by anda_skoa View Post
    only next() and the constructor do [ed.: look ahead].
    Don't know anymore, but to look ahead in the ctor before any hasNext() or next() may have been my blind spot.

    Thank you so much for bearing with me.

    --
    I'd like to change the thread title from "QDirIterator internals?" to "[SOLVED] QDirIterator & regex filter" but can't edit the first post anymore. Admin?

Similar Threads

  1. [TEXTBOOK] Qt Internals and Principles
    By skunkos in forum Qt Programming
    Replies: 0
    Last Post: 30th May 2013, 15:50
  2. Issue using QDir/QDirIterator
    By prophetjohn in forum Newbie
    Replies: 4
    Last Post: 14th September 2011, 05:04
  3. Iterating with QDirIterator seems slow
    By TheShow in forum Qt Programming
    Replies: 1
    Last Post: 6th January 2010, 16:55
  4. QDirIterator and windows drives
    By invictus in forum Qt Programming
    Replies: 0
    Last Post: 8th March 2009, 19:48
  5. QObject Internals Doc
    By sunil.thaha in forum Qt Programming
    Replies: 6
    Last Post: 2nd June 2006, 13:13

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.