int clone(Arguments& info) { if (info.outname.empty()) { std::cout << "You need to specify an output name" << std::endl; return 1; } if (load(info) != 0) { std::cout << "Failed to load, aborting." << std::endl; return 1; } int recordCount = info.data.mRecords.size(); int digitCount = 1; // For a nicer output if (recordCount > 9) ++digitCount; if (recordCount > 99) ++digitCount; if (recordCount > 999) ++digitCount; if (recordCount > 9999) ++digitCount; if (recordCount > 99999) ++digitCount; if (recordCount > 999999) ++digitCount; std::cout << "Loaded " << recordCount << " records:" << std::endl << std::endl; ESM::NAME name; int i = 0; typedef std::map<int, int> Stats; Stats &stats = info.data.mRecordStats; for (Stats::iterator it = stats.begin(); it != stats.end(); ++it) { name.val = it->first; float amount = it->second; std::cout << std::setw(digitCount) << amount << " " << name.toString() << " "; if (++i % 3 == 0) std::cout << std::endl; } if (i % 3 != 0) std::cout << std::endl; std::cout << std::endl << "Saving records to: " << info.outname << "..." << std::endl; ESM::ESMWriter& esm = info.writer; ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding)); esm.setEncoder(&encoder); esm.setAuthor(info.data.author); esm.setDescription(info.data.description); esm.setVersion(info.data.version); esm.setRecordCount (recordCount); for (std::vector<ESM::Header::MasterData>::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it) esm.addMaster(it->name, it->size); std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary); esm.save(save); int saved = 0; typedef std::deque<EsmTool::RecordBase *> Records; Records &records = info.data.mRecords; for (Records::iterator it = records.begin(); it != records.end() && i > 0; ++it) { EsmTool::RecordBase *record = *it; name.val = record->getType().val; esm.startRecord(name.toString(), record->getFlags()); // TODO wrap this with std::set if (ESMData::sLabeledRec.count(name.val) > 0) { esm.writeHNCString("NAME", record->getId()); } else { esm.writeHNOString("NAME", record->getId()); } record->save(esm); if (name.val == ESM::REC_CELL) { ESM::Cell *ptr = &record->cast<ESM::Cell>()->get(); if (!info.data.mCellRefs[ptr].empty()) { typedef std::deque<ESM::CellRef> RefList; RefList &refs = info.data.mCellRefs[ptr]; for (RefList::iterator it = refs.begin(); it != refs.end(); ++it) { it->save(esm); } } } esm.endRecord(name.toString()); saved++; int perc = (saved / (float)recordCount)*100; if (perc % 10 == 0) { std::cerr << "\r" << perc << "%"; } } std::cout << "\rDone!" << std::endl; esm.close(); save.close(); return 0; }
int load(Arguments& info) { ESM::ESMReader& esm = info.reader; ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding)); esm.setEncoder(&encoder); std::string filename = info.filename; std::cout << "Loading file: " << filename << std::endl; std::list<int> skipped; try { if(info.raw_given && info.mode == "dump") { std::cout << "RAW file listing:\n"; esm.openRaw(filename); printRaw(esm); return 0; } bool quiet = (info.quiet_given || info.mode == "clone"); bool loadCells = (info.loadcells_given || info.mode == "clone"); bool save = (info.mode == "clone"); esm.open(filename); info.data.author = esm.getAuthor(); info.data.description = esm.getDesc(); info.data.masters = esm.getGameFiles(); if (!quiet) { std::cout << "Author: " << esm.getAuthor() << std::endl << "Description: " << esm.getDesc() << std::endl << "File format version: " << esm.getFVer() << std::endl; std::vector<ESM::Header::MasterData> m = esm.getGameFiles(); if (!m.empty()) { std::cout << "Masters:" << std::endl; for(unsigned int i=0;i<m.size();i++) std::cout << " " << m[i].name << ", " << m[i].size << " bytes" << std::endl; } } // Loop through all records while(esm.hasMoreRecs()) { ESM::NAME n = esm.getRecName(); uint32_t flags; esm.getRecHeader(flags); // Is the user interested in this record type? bool interested = true; if (info.types.size() > 0) { std::vector<std::string>::iterator match; match = std::find(info.types.begin(), info.types.end(), n.toString()); if (match == info.types.end()) interested = false; } std::string id = esm.getHNOString("NAME"); if(!quiet && interested) std::cout << "\nRecord: " << n.toString() << " '" << id << "'\n"; EsmTool::RecordBase *record = EsmTool::RecordBase::create(n); if (record == 0) { if (std::find(skipped.begin(), skipped.end(), n.val) == skipped.end()) { std::cout << "Skipping " << n.toString() << " records." << std::endl; skipped.push_back(n.val); } esm.skipRecord(); if (quiet) break; std::cout << " Skipping\n"; } else { if (record->getType().val == ESM::REC_GMST) { // preset id for GameSetting record record->cast<ESM::GameSetting>()->get().mId = id; } record->setId(id); record->setFlags((int) flags); record->setPrintPlain(info.plain_given); record->load(esm); if (!quiet && interested) record->print(); if (record->getType().val == ESM::REC_CELL && loadCells) { loadCell(record->cast<ESM::Cell>()->get(), esm, info); } if (save) { info.data.mRecords.push_back(record); } else { delete record; } ++info.data.mRecordStats[n.val]; } } } catch(std::exception &e) { std::cout << "\nERROR:\n\n " << e.what() << std::endl; typedef std::deque<EsmTool::RecordBase *> RecStore; RecStore &store = info.data.mRecords; for (RecStore::iterator it = store.begin(); it != store.end(); ++it) { delete *it; } store.clear(); return 1; } return 0; }