171 lines
4.4 KiB
C++
171 lines
4.4 KiB
C++
/*
|
|
PIP - Platform Independent Primitives
|
|
Resources subsystem
|
|
Ivan Pelipenko peri4ko@yandex.ru
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "piresourcesstorage.h"
|
|
#include "pichunkstream.h"
|
|
#include "piset.h"
|
|
|
|
|
|
PIResourcesStorage::Section::Section() {
|
|
}
|
|
|
|
|
|
PIResourcesStorage::Section::~Section() {
|
|
}
|
|
|
|
|
|
void PIResourcesStorage::Section::add(const PIResourcesStorage::Section & s) {
|
|
auto i = s.entries.makeIterator();
|
|
while (i.next()) {
|
|
if (!i.value()) continue;
|
|
if (entries.value(i.key(), 0)) continue;
|
|
entries[i.key()] = i.value();
|
|
}
|
|
}
|
|
|
|
|
|
void PIResourcesStorage::Section::purge() {
|
|
PIVector<PIByteArray * > bav = entries.values();
|
|
PISet<PIByteArray * > bas;
|
|
piForeach (PIByteArray * i, bav) {
|
|
if (i)
|
|
bas << i;
|
|
}
|
|
bav = bas.toVector();
|
|
piForeach (PIByteArray * i, bav)
|
|
delete i;
|
|
entries.clear();
|
|
}
|
|
|
|
|
|
PIResourcesStorage::PIResourcesStorage() {
|
|
|
|
}
|
|
|
|
|
|
PIResourcesStorage::~PIResourcesStorage() {
|
|
clear();
|
|
}
|
|
|
|
|
|
void PIResourcesStorage::registerSection(const PIString & section_name, const PIResourcesStorage::Section & data) {
|
|
Section * s = sections.value(section_name, 0);
|
|
if (!s) {
|
|
s = new Section();
|
|
sections[section_name] = s;
|
|
}
|
|
s->add(data);
|
|
}
|
|
|
|
|
|
void PIResourcesStorage::registerSection(const uchar * rc_data, const uchar * rc_desc, int rc_desc_size) {
|
|
//piCout << "registerSection" << this;
|
|
PIByteArray dba(rc_desc, rc_desc_size);
|
|
PIVector<PIResourcesStorage::__RCEntry> el;
|
|
dba >> el;
|
|
PIMap<PIString, PIVector<PIResourcesStorage::__RCEntry> > ebs;
|
|
piForeachC (PIResourcesStorage::__RCEntry & e, el) {
|
|
ebs[e.section] << e;
|
|
}
|
|
auto it = ebs.makeIterator();
|
|
while (it.next()) {
|
|
PIResourcesStorage::Section s;
|
|
const PIVector<PIResourcesStorage::__RCEntry> & itv(it.value());
|
|
piForeachC (PIResourcesStorage::__RCEntry & e, itv) {
|
|
//piCout << "add" << e.name << e.alias << PIString::readableSize(e.size);
|
|
PIByteArray * eba = new PIByteArray(&(rc_data[e.offset]), e.size);
|
|
s.entries[e.name] = eba;
|
|
if (!e.alias.isEmpty() && e.alias != e.name)
|
|
s.entries[e.alias] = eba;
|
|
}
|
|
registerSection(it.key(), s);
|
|
}
|
|
}
|
|
|
|
|
|
PIResourcesStorage::Section * PIResourcesStorage::section(const PIString & section_name) const {
|
|
return sections.value(section_name, 0);
|
|
}
|
|
|
|
|
|
PIByteArray PIResourcesStorage::get(const PIString & section_name, const PIString & entry_name) const {
|
|
Section * s = sections.value(section_name, 0);
|
|
if (!s) return PIByteArray();
|
|
PIByteArray * ba = s->entries.value(entry_name, 0);
|
|
if (!ba) return PIByteArray();
|
|
return *ba;
|
|
}
|
|
|
|
|
|
PIByteArray PIResourcesStorage::get(const PIString & entry_name) const {
|
|
auto i = sections.makeIterator();
|
|
while (i.next()) {
|
|
if (!i.value()) continue;
|
|
PIByteArray * ba = i.value()->entries.value(entry_name, 0);
|
|
if (!ba) continue;
|
|
return *ba;
|
|
}
|
|
return PIByteArray();
|
|
}
|
|
|
|
|
|
void PIResourcesStorage::clear() {
|
|
//piCout << "PIResourcesStorage clear";
|
|
PIVector<Section * > sv = sections.values();
|
|
piForeach (Section * i, sv) {
|
|
if (i)
|
|
i->purge();
|
|
}
|
|
sections.clear();
|
|
}
|
|
|
|
|
|
PIResourcesStorage * PIResourcesStorage::instance() {
|
|
static PIResourcesStorage * ret = new PIResourcesStorage();
|
|
return ret;
|
|
}
|
|
|
|
|
|
PIByteArray & operator <<(PIByteArray & b, const PIResourcesStorage::__RCEntry & v) {
|
|
PIChunkStream cs;
|
|
cs << cs.chunk(1, v.section) << cs.chunk(2, v.name) << cs.chunk(3, v.file)
|
|
<< cs.chunk(4, v.size) << cs.chunk(5, v.offset) << cs.chunk(6, v.flags)
|
|
<< cs.chunk(7, v.alias);
|
|
b << cs.data();
|
|
return b;
|
|
}
|
|
|
|
|
|
PIByteArray & operator >>(PIByteArray & b, PIResourcesStorage::__RCEntry & v) {
|
|
PIByteArray ba; b >> ba;
|
|
PIChunkStream cs(ba);
|
|
while (!cs.atEnd()) {
|
|
switch (cs.read()) {
|
|
case 1: cs.get(v.section); break;
|
|
case 2: cs.get(v.name); break;
|
|
case 3: cs.get(v.file); break;
|
|
case 4: cs.get(v.size); break;
|
|
case 5: cs.get(v.offset); break;
|
|
case 6: cs.get(v.flags); break;
|
|
case 7: cs.get(v.alias); break;
|
|
}
|
|
}
|
|
return b;
|
|
}
|