void PropertyMap::save(SavedProperties &p) const { int count = 0; if (!_table) { #if USE_SINGLE_ENTRY if (_singleEntry.key && !(_singleEntry.attributes & (ReadOnly | Function))) ++count; #endif } else { int size = _table->size; Entry *entries = _table->entries; for (int i = 0; i != size; ++i) if (isValid(entries[i].key) && !(entries[i].attributes & (ReadOnly | Function))) ++count; } p._properties.clear(); p._count = count; if (count == 0) return; p._properties.set(new SavedProperty [count]); SavedProperty *prop = p._properties.get(); if (!_table) { #if USE_SINGLE_ENTRY if (_singleEntry.key && !(_singleEntry.attributes & (ReadOnly | Function))) { prop->key = Identifier(_singleEntry.key); prop->value = _singleEntry.value; prop->attributes = _singleEntry.attributes; ++prop; } #endif } else { // Save in the right order so we don't lose the order. // Another possibility would be to save the indices. // Allocate a buffer to use to sort the keys. Vector<Entry*, smallMapThreshold> sortedEntries(count); // Get pointers to the entries in the buffer. Entry** p = sortedEntries.data(); int size = _table->size; Entry* entries = _table->entries; for (int i = 0; i != size; ++i) { Entry *e = &entries[i]; if (isValid(e->key) && !(e->attributes & (ReadOnly | Function))) *p++ = e; } assert(p - sortedEntries.data() == count); // Sort the entries by index. qsort(sortedEntries.data(), p - sortedEntries.data(), sizeof(Entry*), comparePropertyMapEntryIndices); // Put the sorted entries into the saved properties list. for (Entry** q = sortedEntries.data(); q != p; ++q, ++prop) { Entry* e = *q; prop->key = Identifier(e->key); prop->value = e->value; prop->attributes = e->attributes; } } }
int ArcWriter::buildArchive(QString sourceDir, QString outputPath) { QHash<quint32, size_offset_t> oldOffsetToNewSizeOffset; QFile outputFile(outputPath); if(!outputFile.open(QIODevice::WriteOnly)) { return 1; } // Write entries count and data offset outputFile.write((char*)&entriesCount, sizeof(quint32)); outputFile.write((char*)&dataOffset, sizeof(quint32)); // Write undecoded header outputFile.write(undecodedHeader); // Update entries data QVector<arc_entry_t>::iterator it; QVector<arc_entry_t> sortedEntries(entries); qSort(sortedEntries.begin(), sortedEntries.end(), arc_entry_t::lessThan); quint32 accumOffset = sortedEntries.begin()->offset; for( it = sortedEntries.begin(); it != sortedEntries.end(); ++it) { arc_entry_t entry = *it; QString fileName = offsetToFileName.value(entry.offset); QString path = sourceDir + QString("\\") + fileName; QFile fileTmp(path); fileTmp.open(QIODevice::ReadOnly); quint32 realSize = fileTmp.size(); fileTmp.close(); oldOffsetToNewSizeOffset.insert(it->offset, size_offset_t(realSize, accumOffset)); accumOffset += realSize; } sortedEntries.clear(); // Write entries list for( it = entries.begin(); it != entries.end(); ++it) { arc_entry_t entry = *it; // Apply corrections size_offset_t newInfo = oldOffsetToNewSizeOffset.value(entry.offset); entry.offset = newInfo.offset; entry.size = newInfo.size; outputFile.write((char*)&entry, sizeof(arc_entry_t)); } // Copy files data QVector<QString>::iterator file_it; for( file_it = files.begin(); file_it != files.end(); ++file_it) { QString path = sourceDir + QString("\\") + *file_it; QFile fileIn(path); if(!fileIn.open(QIODevice::ReadOnly)) { fprintf(stderr, "File [%s] open failed!\n", path.toAscii().data()); return 1; } /*if (checkSize && (fileIn.size() != file_it->second)) { fprintf(stderr, "File [%s] size check failed!\n", path.toAscii().data()); return 1; }*/ outputFile.write(fileIn.readAll()); fileIn.close(); } outputFile.close(); return 0; }