bool makeCanonical(FS_NAMESPACE::path & result, const FS_NAMESPACE::path & path) { // if we use canonical the file must exits, else we get an exception. try { result = FS_NAMESPACE::canonical(path); } catch (...) { // an error occurred. this maybe because the file is not there yet. try without the file name try { result = FS_NAMESPACE::canonical(FS_NAMESPACE::path(path).remove_filename()); // ok. this worked. add file name again result /= path.filename(); } catch (...) { // hmm. didn't work. tell the user. at least the path should be there... std::cout << "The path \"" << FS_NAMESPACE::path(path).remove_filename().string() << "\" couldn't be found. Please create it." << std::endl; return false; } } return true; }
// This is based on the example code found here: https:// svn.boost.org/trac/boost/ticket/1976 // but changed to not return a trailing ".." when paths only differ in their file name. // The function still seems to be missing in boost as of 1.54.0. FS_NAMESPACE::path naiveUncomplete(FS_NAMESPACE::path const path, FS_NAMESPACE::path const base) { if (path.has_root_path()) { if (path.root_path() != base.root_path()) { return path; } else { return naiveUncomplete(path.relative_path(), base.relative_path()); } } else { if (base.has_root_path()) { return path; } else { auto path_it = path.begin(); auto base_it = base.begin(); while (path_it != path.end() && base_it != base.end()) { if (*path_it != *base_it) break; ++path_it; ++base_it; } FS_NAMESPACE::path result; // check if we're at the filename of the base path already if (*base_it != base.filename()) { // add trailing ".." from path to base, but only if we're not already at the filename of the base path for (; base_it != base.end() && *base_it != base.filename(); ++base_it) { result /= ".."; } } for (; path_it != path.end(); ++path_it) { result /= *path_it; } return result; } } return path; }
int main(int argc, const char * argv[]) { printVersion(); // check number of arguments and if all arguments can be read if (argc < 3 || !readArguments(argc, argv)) { printUsage(); return -1; } // check if the input path exist if (!FS_NAMESPACE::exists(inFilePath)) { std::cout << "Error: Invalid input file/directory \"" << inFilePath.string() << "\"!" << std::endl; return -2; } if (createBinary) { // check if argument 2 is a file if (FS_NAMESPACE::is_directory(outFilePath)) { std::cout << "Error: Output must be a file if -b is used!" << std::endl; return -2; } } else if (appendFile) { // check if argument 2 is a file if (FS_NAMESPACE::is_directory(outFilePath)) { std::cout << "Error: Output must be a file if -a is used!" << std::endl; return -2; } } else if (FS_NAMESPACE::is_directory(inFilePath) != FS_NAMESPACE::is_directory(outFilePath)) { // check if output directory exists if (FS_NAMESPACE::is_directory(outFilePath) && !FS_NAMESPACE::exists(outFilePath)) { std::cout << "Error: Invalid output directory \"" << outFilePath.string() << "\"!" << std::endl; return -2; } // check if arguments 1 and 2 are both files or both directories std::cout << "Error: Input and output file must be both either a file or a directory!" << std::endl; return -2; } if (appendFile) { // append file a to b if (!appendAtoB(outFilePath, inFilePath)) { std::cout << "Error: Failed to append data to executable!" << std::endl; return -3; } } else { // build list of files to process std::vector<FileData> fileList; if (FS_NAMESPACE::is_directory(inFilePath) && FS_NAMESPACE::is_directory(inFilePath)) { // both files are directories, build file ist fileList = getFileDataFrom(inFilePath, outFilePath, inFilePath, useRecursion); if (fileList.empty()) { std::cout << "Error: No files to convert!" << std::endl; return -3; } } else { // just add single input/output file FileData temp; temp.inPath = inFilePath; temp.outPath = outFilePath; temp.internalName = inFilePath.filename().string(); // remove all, but the file name and extension if (beVerbose) { std::cout << "Found input file " << inFilePath << std::endl; std::cout << "Internal name will be \"" << temp.internalName << "\"" << std::endl; std::cout << "Output path is " << temp.outPath << std::endl; } // get file size try { temp.size = static_cast<uint64_t>(FS_NAMESPACE::file_size(inFilePath)); if (beVerbose) { std::cout << "Size is " << temp.size << " bytes." << std::endl; } } catch (...) { std::cout << "Error: Failed to get size of " << inFilePath << "!" << std::endl; temp.size = 0; } fileList.push_back(temp); } // does the user want an binary file? if (createBinary) { // yes. build it. if (!createBlob(fileList, outFilePath)) { std::cout << "Error: Failed to convert to binary file!" << std::endl; return -4; } } else { // no. convert files to .c/.cpp. loop through list, converting files for (auto fdIt = fileList.begin(); fdIt != fileList.cend(); ++fdIt) { if (!convertFile(*fdIt, commonHeaderFilePath)) { std::cout << "Error: Failed to convert all files. Aborting!" << std::endl; return -4; } } // do we need to write a header file? if (!commonHeaderFilePath.empty()) { if (!createCommonHeader(fileList, commonHeaderFilePath, !utilitiesFilePath.empty(), useC)) { return -5; } // do we need to create utilities? if (!utilitiesFilePath.empty()) { if (!createUtilities(fileList, utilitiesFilePath, commonHeaderFilePath, useC, combineResults)) { return -6; } } } } } // if (!appendFile) { // profit!!! std::cout << "res2h succeeded." << std::endl; return 0; }
std::vector<FileData> getFileDataFrom(const FS_NAMESPACE::path & inPath, const FS_NAMESPACE::path & outPath, const FS_NAMESPACE::path & parentDir, const bool recurse) { // get all files from directory std::vector<FileData> files; // check for infinite symlinks if (FS_NAMESPACE::is_symlink(inPath)) { // check if the symlink points somewhere in the path. this would recurse if (inPath.string().find(FS_NAMESPACE::canonical(inPath).string()) == 0) { std::cout << "Warning: Path " << inPath << " contains recursive symlink! Skipping." << std::endl; return files; } } // iterate through source directory searching for files const FS_NAMESPACE::directory_iterator dirEnd; for (FS_NAMESPACE::directory_iterator fileIt(inPath); fileIt != dirEnd; ++fileIt) { FS_NAMESPACE::path filePath = (*fileIt).path(); if (!FS_NAMESPACE::is_directory(filePath)) { if (beVerbose) { std::cout << "Found input file " << filePath << std::endl; } // add file to list FileData temp; temp.inPath = filePath; // replace dots in file name with '_' and add a .c/.cpp extension std::string newFileName = filePath.filename().generic_string(); std::replace(newFileName.begin(), newFileName.end(), '.', '_'); if (useC) { newFileName.append(".c"); } else { newFileName.append(".cpp"); } // remove parent directory of file from path for internal name. This could surely be done in a safer way FS_NAMESPACE::path subPath(filePath.generic_string().substr(parentDir.generic_string().size() + 1)); // add a ":/" before the name to mark internal resources (Yes. Hello Qt!) temp.internalName = ":/" + subPath.generic_string(); // add subdir below parent path to name to enable multiple files with the same name std::string subDirString(subPath.remove_filename().generic_string()); if (!subDirString.empty()) { // replace dir separators by underscores std::replace(subDirString.begin(), subDirString.end(), '/', '_'); // add in front of file name newFileName = subDirString + "_" + newFileName; } // build new output file name temp.outPath = outPath / newFileName; if (beVerbose) { std::cout << "Internal name will be \"" << temp.internalName << "\"" << std::endl; std::cout << "Output path is " << temp.outPath << std::endl; } // get file size try { temp.size = static_cast<uint64_t>(FS_NAMESPACE::file_size(filePath)); if (beVerbose) { std::cout << "Size is " << temp.size << " bytes." << std::endl; } } catch (...) { std::cout << "Error: Failed to get size of " << filePath << "!" << std::endl; temp.size = 0; } // add file to list files.push_back(temp); } } // does the user want subdirectories? if (recurse) { // iterate through source directory again searching for directories for (FS_NAMESPACE::directory_iterator dirIt(inPath); dirIt != dirEnd; ++dirIt) { FS_NAMESPACE::path dirPath = (*dirIt).path(); if (FS_NAMESPACE::is_directory(dirPath)) { if (beVerbose) { std::cout << "Found subdirectory " << dirPath << std::endl; } // subdirectory found. recurse. std::vector<FileData> subFiles = getFileDataFrom(dirPath, outPath, parentDir, recurse); // add returned result to file list files.insert(files.end(), subFiles.cbegin(), subFiles.cend()); } } } // return result return files; }