예제 #1
0
// -----------------------------------------------------------------------------
// Adds the directory structure starting from [start] to [list]
// -----------------------------------------------------------------------------
void Archive::putEntryTreeAsList(vector<shared_ptr<ArchiveEntry>>& list, ArchiveTreeNode* start)
{
	// If no start dir is specified, use the root dir
	if (!start)
		start = &dir_root_;

	// Add the directory entry to the list if it isn't the root dir
	if (start != &dir_root_)
		list.push_back(start->dir_entry_);

	// Add all entries to the list
	for (unsigned a = 0; a < start->numEntries(); a++)
		list.push_back(start->sharedEntryAt(a));

	// Go through subdirectories and add them to the list
	for (unsigned a = 0; a < start->nChildren(); a++)
		putEntryTreeAsList(list, (ArchiveTreeNode*)start->child(a));
}
예제 #2
0
// -----------------------------------------------------------------------------
// Reads pod format data from a MemChunk
// Returns true if successful, false otherwise
// -----------------------------------------------------------------------------
bool PodArchive::open(MemChunk& mc)
{
	// Check data was given
	if (!mc.hasData())
		return false;

	// Read no. of files
	mc.seek(0, 0);
	uint32_t num_files;
	mc.read(&num_files, 4);

	// Read id
	mc.read(id_, 80);

	// Read directory
	vector<FileEntry> files(num_files);
	mc.read(files.data(), num_files * sizeof(FileEntry));

	// Stop announcements (don't want to be announcing modification due to entries being added etc)
	setMuted(true);

	// Create entries
	UI::setSplashProgressMessage("Reading pod archive data");
	for (unsigned a = 0; a < num_files; a++)
	{
		// Get the entry name as a wxFileName (so we can break it up)
		wxFileName fn(files[a].name);

		// Create entry
		auto new_entry              = std::make_shared<ArchiveEntry>(fn.GetFullName(), files[a].size);
		new_entry->exProp("Offset") = files[a].offset;
		new_entry->setLoaded(false);

		// Add entry and directory to directory tree
		string path = fn.GetPath(false);
		auto   ndir = createDir(path);
		ndir->addEntry(new_entry);

		new_entry->setState(ArchiveEntry::State::Unmodified);

		LOG_MESSAGE(5, "File size: %d, offset: %d, name: %s", files[a].size, files[a].offset, files[a].name);
	}

	// Detect entry types
	vector<ArchiveEntry*> all_entries;
	putEntryTreeAsList(all_entries);
	UI::setSplashProgressMessage("Detecting entry types");
	for (unsigned a = 0; a < all_entries.size(); a++)
	{
		// Skip dir/marker
		if (all_entries[a]->size() == 0 || all_entries[a]->type() == EntryType::folderType())
		{
			all_entries[a]->setState(ArchiveEntry::State::Unmodified);
			continue;
		}

		// Update splash window progress
		UI::setSplashProgress((float)a / (float)all_entries.size());

		// Read data
		MemChunk edata;
		mc.exportMemChunk(edata, all_entries[a]->exProp("Offset").intValue(), all_entries[a]->size());
		all_entries[a]->importMemChunk(edata);

		// Detect entry type
		EntryType::detectEntryType(all_entries[a]);

		// Unload entry data if needed
		if (!archive_load_data)
			all_entries[a]->unloadData();

		// Set entry to unchanged
		all_entries[a]->setState(ArchiveEntry::State::Unmodified);
		LOG_MESSAGE(5, "entry %s size %d", CHR(all_entries[a]->name()), all_entries[a]->size());
	}

	// Setup variables
	setMuted(false);
	setModified(false);
	announce("opened");

	UI::setSplashProgressMessage("");

	return true;
}
예제 #3
0
// -----------------------------------------------------------------------------
// Writes the pod archive to a MemChunk
// Returns true if successful, false otherwise
// -----------------------------------------------------------------------------
bool PodArchive::write(MemChunk& mc, bool update)
{
	// Get all entries
	vector<ArchiveEntry*> entries;
	putEntryTreeAsList(entries);

	// Process entries
	int      ndirs     = 0;
	uint32_t data_size = 0;
	for (auto& entry : entries)
	{
		if (entry->type() == EntryType::folderType())
			ndirs++;
		else
			data_size += entry->size();
	}

	// Init MemChunk
	mc.clear();
	mc.reSize(4 + 80 + (entries.size() * 40) + data_size, false);
	LOG_MESSAGE(5, "MC size %d", mc.size());

	// Write no. entries
	uint32_t n_entries = entries.size() - ndirs;
	LOG_MESSAGE(5, "n_entries %d", n_entries);
	mc.write(&n_entries, 4);

	// Write id
	LOG_MESSAGE(5, "id %s", id_);
	mc.write(id_, 80);

	// Write directory
	FileEntry fe;
	fe.offset = 4 + 80 + (n_entries * 40);
	for (auto& entry : entries)
	{
		if (entry->type() == EntryType::folderType())
			continue;

		// Name
		memset(fe.name, 0, 32);
		string path = entry->path(true);
		path.Replace("/", "\\");
		path = path.AfterFirst('\\');
		// LOG_MESSAGE(2, path);
		memcpy(fe.name, CHR(path), path.Len());

		// Size
		fe.size = entry->size();

		// Write directory entry
		mc.write(fe.name, 32);
		mc.write(&fe.size, 4);
		mc.write(&fe.offset, 4);
		LOG_MESSAGE(
			5,
			"entry %s: old=%d new=%d size=%d",
			fe.name,
			entry->exProp("Offset").intValue(),
			fe.offset,
			entry->size());

		// Next offset
		fe.offset += fe.size;
	}

	// Write entry data
	for (auto& entry : entries)
		if (entry->type() != EntryType::folderType())
			mc.write(entry->rawData(), entry->size());

	return true;
}