1 #include "FileArchive.h"
3 #include "ArchiveExtractor.h"
4 #include "MiscInfoFile.h"
8 #include <system_error>
13 using namespace Utils;
14 using namespace std::filesystem;
16 namespace Odb::Lib::FileModel::Design
18 FileArchive::FileArchive()
23 FileArchive::FileArchive(
const std::string& path)
28 FileArchive::~FileArchive()
30 m_stepsByName.clear();
31 m_symbolsDirectoriesByName.clear();
34 std::string FileArchive::GetRootDir()
const
39 std::string FileArchive::GetProductName()
const
44 std::string FileArchive::GetFilePath()
const
49 std::string FileArchive::GetFilename()
const
52 return path(m_filePath).filename().string();
55 const StepDirectory::StringMap& FileArchive::GetStepsByName()
const
60 const SymbolsDirectory::StringMap& FileArchive::GetSymbolsDirectoriesByName()
const
62 return m_symbolsDirectoriesByName;
65 bool FileArchive::ParseFileModel()
69 StopWatch timer(
true);
71 if (!exists(m_filePath))
return false;
73 if (is_regular_file(m_filePath))
76 if (!ExtractDesignArchive(m_filePath, extractedPath))
78 logerror(
"failed to extract archive: (" + m_filePath +
")");
82 m_rootDir = findRootDir(extractedPath);
85 if (is_directory(m_rootDir))
87 loginfo(
"Parsing... ");
89 if (ParseDesignDirectory(m_rootDir))
92 auto s = timer.getElapsedSecondsString();
93 loginfo(
"Successfully parsed. (" + s +
"s)");
99 logerror(
"Parsing failed.");
100 throw std::runtime_error(
"Parsing failed.");
105 logerror(
"Failed to find root directory");
117 bool FileArchive::SaveFileModel(
const path& directory)
119 return SaveFileModel(directory, m_productName);
122 bool FileArchive::SaveFileModel(
const path& directory,
const std::string& archiveName)
129 char szTmpNameBuff[L_tmpnam] = { 0 };
130 if (
nullptr == std::tmpnam(szTmpNameBuff))
return false;
132 auto tempPath = temp_directory_path() / szTmpNameBuff;
133 if (!create_directory(tempPath))
return false;
135 auto rootPath = tempPath / archiveName;
136 if (!create_directory(rootPath))
return false;
137 if (!Save(rootPath))
return false;
140 std::string createdArchivePath;
141 if (! Utils::ArchiveExtractor::CompressDir(rootPath.string(), tempPath.string(), archiveName, createdArchivePath))
return false;
142 if (createdArchivePath.empty())
return false;
145 path archiveFilename = path(createdArchivePath).filename();
146 path destPath = directory / archiveFilename;
148 Utils::fastmove_file(createdArchivePath, destPath,
true, ec);
149 if (ec.value() != 0)
return false;
154 bool FileArchive::Save(
const path& directory)
157 auto miscPath = directory /
"misc";
158 if (!create_directory(miscPath))
return false;
160 std::ofstream ofs1(miscPath /
"info", std::ios::out);
161 if (!m_miscInfoFile.Save(ofs1))
return false;
165 std::ofstream ofs2(miscPath /
"sysattr");
166 if (!m_miscAttrListFile.Save(ofs2))
return false;
170 auto fontsPath = directory /
"fonts";
171 if (!create_directory(fontsPath))
return false;
172 std::ofstream ofs3(fontsPath /
"standard");
173 if (!m_standardFontsFile.Save(ofs3))
return false;
177 auto matrixPath = directory /
"matrix";
178 if (!create_directory(matrixPath))
return false;
179 std::ofstream ofs4(matrixPath /
"matrix");
180 if (!m_matrixFile.Save(ofs4))
return false;
184 const auto stepsDirectory = directory /
"steps";
185 if (!create_directory(stepsDirectory))
return false;
186 for (
auto& kvStepDirectory : m_stepsByName)
188 if (!kvStepDirectory.second->Save(stepsDirectory))
return false;
192 const auto symbolsDirectory = directory /
"symbols";
193 if (!create_directory(symbolsDirectory))
return false;
194 for (
auto& kvSymbolsDirectory : m_symbolsDirectoriesByName)
196 if (!kvSymbolsDirectory.second->Save(symbolsDirectory))
return false;
202 bool FileArchive::ExtractDesignArchive(
const path& archivePath, path& extractedPath)
204 loginfo(
"Extracting... ");
206 if (!Utils::ArchiveExtractor::IsArchiveTypeSupported(archivePath))
208 logerror(
"Unsupported archive type: (" + archivePath.string() +
")");
212 Utils::ArchiveExtractor extractor(archivePath.string());
213 if (!extractor.Extract())
return false;
215 auto extracted = path(extractor.GetExtractionDirectory());
216 if (!exists(extracted))
return false;
218 extractedPath = extracted;
220 loginfo(
"Successfully extracted.");
226 std::string FileArchive::findRootDir(
const path& extractedPath)
228 if (pathContainsTopLevelDesignDirs(extractedPath))
230 return extractedPath.string();
234 for (
const auto& p : directory_iterator(extractedPath))
238 if (pathContainsTopLevelDesignDirs(p.path()))
240 return p.path().string();
249 bool FileArchive::pathContainsTopLevelDesignDirs(
const path& path)
251 for (
const auto& topLevelRootDirName : TOPLEVEL_DESIGN_DIR_NAMES)
253 auto rootLevelDirPath = path / topLevelRootDirName;
254 if (!exists(rootLevelDirPath))
return false;
259 std::unique_ptr<Protobuf::FileArchive> FileArchive::to_protobuf()
const
261 std::unique_ptr<Protobuf::FileArchive> pFileArchiveMessage(
new Protobuf::FileArchive);
262 pFileArchiveMessage->set_productname(m_productName);
263 pFileArchiveMessage->set_filename(m_filename);
265 pFileArchiveMessage->mutable_matrixfile()->CopyFrom(*m_matrixFile.to_protobuf());
266 pFileArchiveMessage->mutable_miscinfofile()->CopyFrom(*m_miscInfoFile.to_protobuf());
267 pFileArchiveMessage->mutable_standardfontsfile()->CopyFrom(*m_standardFontsFile.to_protobuf());
268 pFileArchiveMessage->mutable_miscattrlistfile()->CopyFrom(*m_miscAttrListFile.to_protobuf());
270 for (
const auto& kvStepDirectoryRecord : m_stepsByName)
272 (*pFileArchiveMessage->mutable_stepsbyname())[kvStepDirectoryRecord.first] = *kvStepDirectoryRecord.second->to_protobuf();
275 for (
const auto& kvSymbolsDirectory : m_symbolsDirectoriesByName)
277 (*pFileArchiveMessage->mutable_symbolsdirectoriesbyname())[kvSymbolsDirectory.first] = *kvSymbolsDirectory.second->to_protobuf();
280 return pFileArchiveMessage;
283 void FileArchive::from_protobuf(
const Protobuf::FileArchive& message)
285 m_productName = message.productname();
286 m_filename = message.filename();
288 m_matrixFile.from_protobuf(message.matrixfile());
289 m_miscInfoFile.from_protobuf(message.miscinfofile());
290 m_standardFontsFile.from_protobuf(message.standardfontsfile());
291 m_miscAttrListFile.from_protobuf(message.miscattrlistfile());
293 for (
const auto& kvStepDirectoryRecord : message.stepsbyname())
295 auto pStepDirectory = std::make_shared<StepDirectory>(
"");
296 pStepDirectory->from_protobuf(kvStepDirectoryRecord.second);
297 m_stepsByName[kvStepDirectoryRecord.first] = pStepDirectory;
300 for (
const auto& kvSymbolsDirectory : message.symbolsdirectoriesbyname())
302 auto pSymbolsDirectory = std::make_shared<SymbolsDirectory>(
"");
303 pSymbolsDirectory->from_protobuf(kvSymbolsDirectory.second);
304 m_symbolsDirectoriesByName[kvSymbolsDirectory.first] = pSymbolsDirectory;
308 bool FileArchive::ParseDesignDirectory(
const path& path)
310 if (!exists(path))
return false;
311 else if (!is_directory(path))
return false;
313 m_productName = path.stem().string();
315 if (! ParseStepDirectories(path))
return false;
316 if (! ParseMiscInfoFile(path))
return false;
317 if (! ParseMatrixFile(path))
return false;
318 if (! ParseStandardFontsFile(path))
return false;
319 if (! ParseSymbolsDirectories(path))
return false;
320 if (! ParseMiscAttrListFile(path))
return false;
325 bool FileArchive::ParseStepDirectories(
const path& path)
327 loginfo(
"Parsing steps...");
329 auto stepsPath = path /
"steps";
330 for (
auto& d : directory_iterator(stepsPath))
334 auto pStep = std::make_shared<StepDirectory>(d.path());
337 m_stepsByName[pStep->GetName()] = pStep;
341 logwarn(
"Failed to parse step: " + pStep->GetName());
347 loginfo(
"Parsing steps complete");
352 bool FileArchive::ParseMiscInfoFile(
const path& path)
354 loginfo(
"Parsing misc/info file...");
356 auto miscDirectory = path /
"misc";
357 if (!exists(miscDirectory))
return false;
358 if (!is_directory(miscDirectory))
return false;
360 if (!m_miscInfoFile.Parse(miscDirectory))
return false;
362 loginfo(
"Parsing misc/info file complete");
367 bool FileArchive::ParseMiscAttrListFile(
const path& path)
369 loginfo(
"Parsing misc/attrlist file...");
371 auto miscDirectory = path /
"misc";
372 if (!exists(miscDirectory))
return false;
373 if (!is_directory(miscDirectory))
return false;
375 if (!m_miscAttrListFile.Parse(miscDirectory))
return false;
377 loginfo(
"Parsing misc/attrlist file complete");
382 bool FileArchive::ParseMatrixFile(
const path& path)
384 loginfo(
"Parsing matrix/matrix file...");
386 auto matrixDir = path /
"matrix";
387 if (!exists(matrixDir))
return false;
388 if (!is_directory(matrixDir))
return false;
390 if (!m_matrixFile.Parse(matrixDir))
return false;
392 loginfo(
"Parsing matrix/matrix file complete");
396 bool FileArchive::ParseStandardFontsFile(
const path& path)
398 loginfo(
"Parsing fonts/standard file...");
400 auto fontsDir = path /
"fonts";
401 if (!exists(fontsDir))
return false;
402 if (!is_directory(fontsDir))
return false;
404 if (!m_standardFontsFile.Parse(fontsDir))
return false;
406 loginfo(
"Parsing fonts/standard file complete");
411 bool FileArchive::ParseSymbolsDirectories(
const path& path)
413 loginfo(
"Parsing symbols root directory...");
415 auto symbolsDirectory = path /
"symbols";
417 if (!exists(symbolsDirectory))
419 logwarn(
"symbols root directory does not exist (" + symbolsDirectory.string() +
")");
422 else if (!is_directory(symbolsDirectory))
424 logerror(
"symbols root directory exists but is a regular file/not a directory (" + symbolsDirectory.string() +
")");
428 for (
auto& d : directory_iterator(symbolsDirectory))
432 auto pSymbolsDirectory = std::make_shared<SymbolsDirectory>(d.path());
433 if (pSymbolsDirectory->Parse())
437 m_symbolsDirectoriesByName[pSymbolsDirectory->GetName()] = pSymbolsDirectory;
441 logerror(
"Parsing symbol directory: " + pSymbolsDirectory->GetName() +
" failed");
447 loginfo(
"Parsing symbols root directory complete");
452 const MiscInfoFile &FileArchive::GetMiscInfoFile()
const
454 return m_miscInfoFile;
457 const MatrixFile& FileArchive::GetMatrixFile()
const
462 const StandardFontsFile& FileArchive::GetStandardFontsFile()
const
464 return m_standardFontsFile;
467 const AttrListFile& FileArchive::GetMiscAttrListFile()
const
469 return m_miscAttrListFile;
472 std::shared_ptr<StepDirectory> FileArchive::GetStepDirectory(
const std::string& stepName )
const
474 std::shared_ptr<FileModel::Design::StepDirectory> pStepDirectory;
476 const auto& steps = GetStepsByName();
479 if (stepName.empty())
482 pStepDirectory = steps.begin()->second;
486 auto findIt = steps.find(stepName);
487 if (findIt != steps.end())
489 pStepDirectory = findIt->second;
494 return pStepDirectory;