Skip to content

Commit

Permalink
libcore: Fixes for DirectoryFeed; Folder uses case-insensitive keys
Browse files Browse the repository at this point in the history
  • Loading branch information
skyjake committed Sep 1, 2019
1 parent f8b0314 commit e8e92c5
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 43 deletions.
26 changes: 16 additions & 10 deletions doomsday/libs/core/include/de/data/hash.h
Expand Up @@ -27,10 +27,13 @@ namespace de {
* Efficient key-value container with unordered keys (based on std::unordered_map).
* @ingroup data
*/
template <typename Key, typename Value>
class Hash : public std::unordered_map<Key, Value>
template <typename Key,
typename Value,
typename HashFn = std::hash<Key>,
typename KeyEqual = std::equal_to<Key>>
class Hash : public std::unordered_map<Key, Value, HashFn, KeyEqual>
{
using Base = std::unordered_map<Key, Value>;
using Base = std::unordered_map<Key, Value, HashFn, KeyEqual>;

public:
Hash() {}
Expand Down Expand Up @@ -65,30 +68,33 @@ class Hash : public std::unordered_map<Key, Value>
}
};

template <typename Key, typename Value>
template <typename Key,
typename Value,
typename HashFn = std::hash<Key>,
typename KeyEqual = std::equal_to<Key>>
class MutableHashIterator
{
using Container = Hash<Key, Value>;
using Container = Hash<Key, Value, HashFn, KeyEqual>;
using Iterator = typename Container::iterator;

Container _hash;
Iterator _iter;
Iterator _cur;
Iterator _next;

public:
MutableHashIterator(Container &c) : _hash(c)
{
if (!_hash.empty()) _next = c.begin();
_iter = _hash.begin();
}

bool hasNext() const
{
return !_hash.empty() && _next != _hash.end();
return _iter != _hash.end();
}

Iterator &next()
{
_cur = _next++;
_cur = _iter++;
return _cur;
}

Expand All @@ -104,7 +110,7 @@ class MutableHashIterator

void remove()
{
_hash.erase(_cur);
_iter = _hash.erase(_cur);
}
};
} // namespace de
Expand Down
21 changes: 10 additions & 11 deletions doomsday/libs/core/include/de/data/map.h
Expand Up @@ -26,10 +26,10 @@ namespace de {
/**
* Key-value container with ordered keys (based on std::map).
*/
template <typename Key, typename Value>
class Map : public std::map<Key, Value>
template <typename Key, typename Value, typename Compare = std::less<Key>>
class Map : public std::map<Key, Value, Compare>
{
using Base = std::map<Key, Value>;
using Base = std::map<Key, Value, Compare>;

public:
Map() {}
Expand Down Expand Up @@ -59,31 +59,30 @@ class Map : public std::map<Key, Value>
}
};

template <typename Key, typename Value>
template <typename Key, typename Value, typename Compare = std::less<Key>>
class MutableMapIterator
{
using Container = Map<Key, Value>;
using Container = Map<Key, Value, Compare>;
using Iterator = typename Container::iterator;

Container _map;
Iterator _iter;
Iterator _cur;
Iterator _next;

public:
MutableMapIterator(Container &c) : _map(c)
{
if (!_map.empty()) _next = c.begin();
_iter = _map.begin();
}

bool hasNext() const
{
return !_map.empty() && _next != _map.end();
return _iter != _map.end();
}

Iterator &next()
{
_cur = _next;
if (hasNext()) ++_next;
_cur = _iter++;
return _cur;
}

Expand All @@ -99,7 +98,7 @@ class MutableMapIterator

void remove()
{
_map.erase(_cur);
_iter = _map.erase(_cur);
}
};

Expand Down
2 changes: 1 addition & 1 deletion doomsday/libs/core/include/de/data/time.h
Expand Up @@ -170,7 +170,7 @@ class DE_PUBLIC Time : public ISerializable
Time(Time &&moved);

Time(const TimePoint &tp);
Time(iTime time);
Time(const iTime &time);

Time(int year, int month, int day, int hour, int minute, int second);

Expand Down
2 changes: 1 addition & 1 deletion doomsday/libs/core/include/de/filesys/folder.h
Expand Up @@ -67,7 +67,7 @@ class DE_PUBLIC Folder : public File
DE_ERROR(NewFileError);

typedef List<Feed *> Feeds;
typedef Map<String, File *> Contents;
typedef Map<String, File *, String::InsensitiveLessThan> Contents;

enum PopulationBehavior {
PopulateFullTree = 0x1, ///< The full tree is populated.
Expand Down
2 changes: 1 addition & 1 deletion doomsday/libs/core/src/data/time.cpp
Expand Up @@ -285,7 +285,7 @@ Time::Time(int year, int month, int day, int hour, int minute, int second)
Time::Time(const TimePoint &tp) : d(new Impl(tp))
{}

Time::Time(iTime time) : d(new Impl)
Time::Time(const iTime &time) : d(new Impl(0 /* init as invalid */))
{
using namespace std::chrono;
d->flags |= Impl::SysTime;
Expand Down
1 change: 0 additions & 1 deletion doomsday/libs/core/src/filesys/directoryfeed.cpp
Expand Up @@ -106,7 +106,6 @@ Feed::PopulatedFiles DirectoryFeed::populate(Folder const &folder)
{
continue;
}
if (name == ".." || name.first() == '.') continue;

if (isDirectory_FileInfo(i.value))
{
Expand Down
2 changes: 1 addition & 1 deletion doomsday/libs/core/src/filesys/file.cpp
Expand Up @@ -81,7 +81,7 @@ File::~File()
{
// If we own a source, get rid of it.
delete d->source;
d->source = 0;
d->source = nullptr;
}
if (Folder *parentFolder = parent())
{
Expand Down
35 changes: 18 additions & 17 deletions doomsday/libs/core/src/filesys/folder.cpp
Expand Up @@ -66,7 +66,7 @@ DE_PIMPL(Folder)

void add(File *file)
{
contents.insert(file->name().lower(), file);
contents.insert(file->name(), file);
file->setParent(thisPublic);
}

Expand Down Expand Up @@ -216,22 +216,21 @@ void Folder::populate(PopulationBehaviors behavior)
DE_GUARD(this);

// Prune the existing files first.
MutableMapIterator<String, File *> iter(d->contents);
while (iter.hasNext())
for (auto iter = d->contents.begin(); iter != d->contents.end(); )
{
iter.next();

// By default we will NOT prune if there are no feeds attached to the folder.
// In this case the files were probably created manually, so we shouldn't
// touch them.
bool mustPrune = false;

File *file = iter.value();
File *file = iter->second;
if (file->mode() & DontPrune)
{
// Skip this one, it should be kept as-is until manually deleted.
++iter;
continue;
}

Feed *originFeed = file->originFeed();

// If the file has a designated feed, ask it about pruning.
Expand All @@ -245,11 +244,11 @@ void Folder::populate(PopulationBehaviors behavior)
// There is no designated feed, ask all feeds of this folder.
// If even one of the feeds thinks that the file is out of date,
// it will be pruned.
for (Feeds::iterator f = d->feeds.begin(); f != d->feeds.end(); ++f)
for (auto *f : d->feeds)
{
if ((*f)->prune(*file))
if (f->prune(*file))
{
LOG_RES_XVERBOSE("Pruning %s due to non-origin feed %s", file->path() << (*f)->description());
LOG_RES_XVERBOSE("Pruning %s due to non-origin feed %s", file->path() << f->description());
mustPrune = true;
break;
}
Expand All @@ -260,9 +259,13 @@ void Folder::populate(PopulationBehaviors behavior)
{
// It needs to go.
file->setParent(nullptr);
iter.remove();
iter = d->contents.erase(iter);
delete file;
}
else
{
++iter;
}
}
}

Expand All @@ -283,7 +286,7 @@ void Folder::populate(PopulationBehaviors behavior)
if (i)
{
std::unique_ptr<File> file(i);
if (!d->contents.contains(i->name().lower()))
if (!d->contents.contains(i->name()))
{
d->add(file.release());
fileSystem().index(*i);
Expand Down Expand Up @@ -475,7 +478,7 @@ bool Folder::has(String const &name) const
}

DE_GUARD(this);
return (d->contents.find(name.lower()) != d->contents.end());
return (d->contents.find(name) != d->contents.end());
}

File &Folder::add(File *file)
Expand All @@ -498,10 +501,8 @@ File *Folder::remove(const String &name)
{
DE_GUARD(this);

String const key = name.lower();
DE_ASSERT(d->contents.contains(key));

File *removed = d->contents.take(key);
DE_ASSERT(d->contents.contains(name));
File *removed = d->contents.take(name);
removed->setParent(nullptr);
return removed;
}
Expand All @@ -520,7 +521,7 @@ filesys::Node const *Folder::tryGetChild(String const &name) const
{
DE_GUARD(this);

auto found = d->contents.find(name.lower());
auto found = d->contents.find(name);
if (found != d->contents.end())
{
return found->second;
Expand Down

0 comments on commit e8e92c5

Please sign in to comment.