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 | |
36 | namespace resources { |
37 | |
38 | std::unordered_map<string, ResourceDirectory> internal::g_directories; |
39 | std::unordered_map<string, ResourceFile> internal::g_resources; |
40 | ResourceDirectory internal::g_resources_root; |
41 | |
42 | /* Class Members of ResourceFile */ |
43 | const ResourceFile* ResourceFile::get(const string& dir, const string& file) { |
44 | return get(dir + '/' + file); |
45 | } |
46 | const 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 */ |
52 | void ResourceDirectory::addFile(ResourceFile* r) { |
53 | OGDF_ASSERT(r != nullptr); |
54 | m_files[r->name()] = r; |
55 | } |
56 | |
57 | void ResourceDirectory::addDirectory(ResourceDirectory* r) { |
58 | OGDF_ASSERT(r != nullptr); |
59 | m_directories[r->name()] = r; |
60 | } |
61 | ResourceDirectory* 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 | |
70 | const 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 | } |
75 | const 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 | } |
80 | ResourceDirectory* 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 | |
89 | const 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 | } |
98 | const 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 | } |
107 | ResourceDirectory* 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 | |
127 | std::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 | } |
134 | std::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 | |
142 | void 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 | |
155 | const ResourceDirectory* ResourceDirectory::get(const string& dir, const string& name) { |
156 | return get(dir + '/' + name); |
157 | } |
158 | const 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 */ |
164 | void 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 | |