1/** \file
2 * \brief Resource file abstraction to be used in tests. Resources
3 * are compiled into binary format and can be accessed with the
4 * classes provided by this file.
5 *
6 * \author Jöran Schierbaum
7 *
8 * \par License:
9 * This file is part of the Open Graph Drawing Framework (OGDF).
10 *
11 * \par
12 * Copyright (C)<br>
13 * See README.md in the OGDF root directory for details.
14 *
15 * \par
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * Version 2 or 3 as published by the Free Software Foundation;
19 * see the file LICENSE.txt included in the packaging of this file
20 * for details.
21 *
22 * \par
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * \par
29 * You should have received a copy of the GNU General Public
30 * License along with this program; if not, see
31 * http://www.gnu.org/copyleft/gpl.html
32 */
33
34#include <resources.h>
35
36namespace resources {
37
38std::unordered_map<string, ResourceDirectory> internal::g_directories;
39std::unordered_map<string, ResourceFile> internal::g_resources;
40ResourceDirectory internal::g_resources_root;
41
42/* Class Members of ResourceFile */
43const ResourceFile* ResourceFile::get(const string& dir, const string& file) {
44 return get(dir + '/' + file);
45}
46const ResourceFile* ResourceFile::get(const string& path) {
47 if (internal::g_resources.find(path) == internal::g_resources.end()) return nullptr;
48 return &internal::g_resources[path];
49}
50
51/* Class Members of ResourceDirectory */
52void ResourceDirectory::addFile(ResourceFile* r) {
53 OGDF_ASSERT(r != nullptr);
54 m_files[r->name()] = r;
55}
56
57void ResourceDirectory::addDirectory(ResourceDirectory* r) {
58 OGDF_ASSERT(r != nullptr);
59 m_directories[r->name()] = r;
60}
61ResourceDirectory* ResourceDirectory::addDirectory(const string& name) {
62 ResourceDirectory newdir(fullPath(), name);
63 // Copy into global array and return address from that
64 internal::g_directories[newdir.fullPath()] = newdir;
65 ResourceDirectory* p = &internal::g_directories[newdir.fullPath()];
66 addDirectory(p);
67 return p;
68}
69
70const ResourceFile* ResourceDirectory::getFile(const string& name) const {
71 auto it = m_files.find(name);
72 if (it == m_files.end()) return nullptr;
73 return it->second;
74}
75const ResourceDirectory* ResourceDirectory::getDirectory(const string& name) const {
76 auto it = m_directories.find(name);
77 if (it == m_directories.end()) return nullptr;
78 return it->second;
79}
80ResourceDirectory* ResourceDirectory::getDirectory(const string& name, bool create) {
81 auto it = m_directories.find(name);
82 if (it == m_directories.end()) {
83 if (create) return addDirectory(name);
84 return nullptr;
85 }
86 return it->second;
87}
88
89const ResourceFile* ResourceDirectory::getFileByPath(const string& path) const {
90 string::size_type pos = path.find('/');
91 if (pos == string::npos) {
92 return getFile(path);
93 }
94 const ResourceDirectory* next = getDirectory(path.substr(0, pos));
95 if (next == nullptr) return nullptr; // no such directory
96 return next->getFileByPath(path.substr(pos + 1));
97}
98const ResourceDirectory* ResourceDirectory::getDirectoryByPath(const string& path) const {
99 string::size_type pos = path.find('/');
100 if (pos == string::npos) {
101 return getDirectory(path);
102 }
103 const ResourceDirectory* next = getDirectory(path.substr(0, pos));
104 if (next == nullptr) return next; // no such directory
105 return next->getDirectoryByPath(path.substr(pos + 1));
106}
107ResourceDirectory* ResourceDirectory::getDirectoryByPath(const string& path, bool createPath) {
108 string::size_type pos = path.find('/');
109 if (pos == string::npos) {
110 ResourceDirectory* found = getDirectory(path);
111 if (found == nullptr && createPath) {
112 found = addDirectory(path);
113 }
114 return found;
115 }
116 ResourceDirectory* next = getDirectory(path.substr(0, pos));
117 if (next == nullptr) {
118 // no such directory
119 if (!createPath) {
120 return nullptr;
121 }
122 next = addDirectory(path.substr(0, pos));
123 }
124 return next->getDirectoryByPath(path.substr(pos + 1), createPath);
125}
126
127std::vector<const ResourceFile*> ResourceDirectory::getFiles() const {
128 std::vector<const ResourceFile*> entries;
129 for (auto it : m_files) {
130 entries.push_back(it.second);
131 }
132 return entries;
133}
134std::vector<const ResourceDirectory*> ResourceDirectory::getDirectories() const {
135 std::vector<const ResourceDirectory*> entries;
136 for (auto it : m_directories) {
137 entries.push_back(it.second);
138 }
139 return entries;
140}
141
142void ResourceDirectory::forEachFile(std::function<void(const ResourceFile*)> callback, bool recurse) const {
143 for (auto it : m_files) {
144 callback(it.second);
145 }
146
147 if (recurse) {
148 for (auto it : m_directories) {
149 if (it.second == nullptr) continue;
150 it.second->forEachFile(callback, true);
151 }
152 }
153}
154
155const ResourceDirectory* ResourceDirectory::get(const string& dir, const string& name) {
156 return get(dir + '/' + name);
157}
158const ResourceDirectory* ResourceDirectory::get(const string& path) {
159 if (internal::g_directories.find(path) == internal::g_directories.end()) return nullptr;
160 return &internal::g_directories[path];
161}
162
163/* Global methods */
164void internal::registerResource(const string& directory, const string& filename, const string& contents) {
165 ResourceDirectory* dir = g_resources_root.getDirectoryByPath(directory, true);
166 ResourceFile f(directory, filename, contents);
167 // Copy into global array, store address of that copy
168 g_resources[directory + '/' + filename] = f;
169 dir->addFile(&g_resources[directory + '/' + filename]);
170}
171
172}
173