bool createUtilities(std::vector<FileData> & fileList, const FS_NAMESPACE::path & utilitiesPath, const FS_NAMESPACE::path & commonHeaderPath, bool useCConstructs = false, bool addFileData = false) { // try opening the output file. truncate it when it exists std::ofstream outStream; outStream.open(utilitiesPath.generic_string(), std::ofstream::out | std::ofstream::trunc); if (outStream.is_open() && outStream.good()) { if (beVerbose) { std::cout << std::endl << "Creating utilities file " << utilitiesPath; } // add message outStream << "// this file was auto-generated by res2h" << std::endl << std::endl; // create path to include file RELATIVE to this file FS_NAMESPACE::path relativePath = naiveUncomplete(commonHeaderPath, utilitiesPath); // include header file outStream << "#include \"" << relativePath.string() << "\"" << std::endl << std::endl; // if the data should go to this file too, add it if (addFileData) { for (auto fdIt = fileList.begin(); fdIt != fileList.cend(); ++fdIt) { if (!convertFile(*fdIt, commonHeaderFilePath, outStream, false)) { std::cout << "Error: Failed to convert all files. Aborting!" << std::endl; outStream.close(); return false; } } } // begin data arrays. switch depending whether C or C++ outStream << "const uint32_t res2hNrOfFiles = " << fileList.size() << ";" << std::endl; // add files outStream << "const Res2hEntry res2hFiles[res2hNrOfFiles] = {" << std::endl; outStream << " "; // first indent for (auto fdIt = fileList.cbegin(); fdIt != fileList.cend();) { outStream << "{\"" << fdIt->internalName << "\", " << fdIt->sizeVariableName << ", " << fdIt->dataVariableName << "}"; // was this the last entry? ++fdIt; if (fdIt != fileList.cend()) { // no. add comma. outStream << ","; // add break after every entry and add indent again outStream << std::endl << " "; } } outStream << std::endl << "};" << std::endl; if (!useCConstructs) { // add files to map outStream << std::endl << "res2hMapType::value_type mapTemp[] = {" << std::endl; outStream << " "; for (auto fdIt = fileList.cbegin(); fdIt != fileList.cend();) { outStream << "std::make_pair(\"" << fdIt->internalName << "\", res2hFiles[" << (fdIt - fileList.cbegin()) << "])"; // was this the last entry? ++fdIt; if (fdIt != fileList.cend()) { // no. add comma. outStream << ","; // add break after every entry and add indent again outStream << std::endl << " "; } } outStream << std::endl << "};" << std::endl << std::endl; // create map outStream << "res2hMapType res2hMap(mapTemp, mapTemp + sizeof mapTemp / sizeof mapTemp[0]);" << std::endl; } // close file outStream.close(); if (beVerbose) { std::cout << " - succeeded." << std::endl; } return true; } else { std::cout << "Error: Failed to open file \"" << utilitiesPath << "\" for writing!" << std::endl; } return true; }
bool createCommonHeader(const std::vector<FileData> & fileList, const FS_NAMESPACE::path & commonHeaderPath, bool addUtilityFunctions = false, bool useCConstructs = false) { // try opening the output file. truncate it when it exists std::ofstream outStream; outStream.open(commonHeaderPath.generic_string(), std::ofstream::out | std::ofstream::trunc); if (outStream.is_open() && outStream.good()) { if (beVerbose) { std::cout << std::endl << "Creating common header " << commonHeaderPath; } // add message outStream << "// this file was auto-generated by res2h" << std::endl << std::endl; // add #pragma to only include once outStream << "#pragma once" << std::endl << std::endl; // add includes for C++ if (!useCConstructs) { outStream << "#include <string>" << std::endl; if (addUtilityFunctions) { outStream << "#include <map>" << std::endl; } outStream << std::endl; } // add all files and check maximum size uint64_t maxSize = 0; for (auto fdIt = fileList.cbegin(); fdIt != fileList.cend(); ++fdIt) { // add size and data variable maxSize = maxSize < fdIt->size ? fdIt->size : maxSize; if (fdIt->size <= UINT16_MAX) { outStream << "extern const uint16_t "; } else if (fdIt->size <= UINT32_MAX) { outStream << "extern const uint32_t "; } else { outStream << "extern const uint64_t "; } outStream << fdIt->sizeVariableName << ";" << std::endl; outStream << "extern const uint8_t " << fdIt->dataVariableName << "[];" << std::endl << std::endl; } // if we want utilities, add array if (addUtilityFunctions) { // add resource struct outStream << "struct Res2hEntry {" << std::endl; if (useCConstructs) { outStream << " const char * relativeFileName;" << std::endl; } else { outStream << " const std::string relativeFileName;" << std::endl; } // add size member depending on the determined maximum file size if (maxSize <= UINT16_MAX) { outStream << " const uint16_t size;" << std::endl; } else if (maxSize <= UINT32_MAX) { outStream << " const uint32_t size;" << std::endl; } else { outStream << " const uint64_t size;" << std::endl; } outStream << " const uint8_t * data;" << std::endl; outStream << "};" << std::endl << std::endl; // add list holding files outStream << "extern const uint32_t res2hNrOfFiles;" << std::endl; outStream << "extern const Res2hEntry res2hFiles[];" << std::endl << std::endl; if (!useCConstructs) { // add additional std::map if C++ outStream << "typedef const std::map<const std::string, const Res2hEntry> res2hMapType;" << std::endl; outStream << "extern res2hMapType res2hMap;" << std::endl; } } // close file outStream.close(); if (beVerbose) { std::cout << " - succeeded." << std::endl; } return true; } else { std::cout << "Error: Failed to open file \"" << commonHeaderPath << "\" for writing!" << std::endl; } return true; }
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; }
bool convertFile(FileData & fileData, const FS_NAMESPACE::path & commonHeaderPath, std::ofstream & outStream = badOfStream, bool addHeader = true) { if (FS_NAMESPACE::exists(fileData.inPath)) { // try to open the input file std::ifstream inStream; inStream.open(fileData.inPath.string(), std::ifstream::in | std::ifstream::binary); if (inStream.is_open() && inStream.good()) { if (beVerbose) { std::cout << "Converting input file " << fileData.inPath; } // try getting size of data inStream.seekg(0, std::ios::end); fileData.size = static_cast<uint64_t>(inStream.tellg()); inStream.seekg(0); // check if the caller passed and output stream and use that bool closeOutStream = false; if (!outStream.is_open() || !outStream.good()) { if (!fileData.outPath.empty()) { // try opening the output stream. truncate it when it exists outStream.open(fileData.outPath.string(), std::ofstream::out | std::ofstream::trunc); } else { std::cout << "Error: No output stream passed, but output path for \"" << fileData.inPath.filename().string() << "\" is empty! Skipping." << std::endl; return false; } closeOutStream = true; } // now write to stream if (outStream.is_open() && outStream.good()) { // check if caller want to add a header if (addHeader) { // add message outStream << "// this file was auto-generated from \"" << fileData.inPath.filename().string() << "\" by res2h" << std::endl << std::endl; // add header include if (!commonHeaderPath.empty()) { // common header path must be relative to destination directory FS_NAMESPACE::path relativeHeaderPath = naiveUncomplete(commonHeaderPath, fileData.outPath); outStream << "#include \"" << relativeHeaderPath.generic_string() << "\"" << std::endl << std::endl; } } // create names for variables fileData.dataVariableName = fileData.outPath.filename().stem().string() + "_data"; fileData.sizeVariableName = fileData.outPath.filename().stem().string() + "_size"; // add size and data variable if (fileData.size <= UINT16_MAX) { outStream << "const uint16_t "; } else if (fileData.size <= UINT32_MAX) { outStream << "const uint32_t "; } else { outStream << "const uint64_t "; } outStream << fileData.sizeVariableName << " = " << std::dec << fileData.size << ";" << std::endl; outStream << "const uint8_t " << fileData.dataVariableName << "[" << std::dec << fileData.size << "] = {" << std::endl; outStream << " "; // first indent // now add content uint64_t breakCounter = 0; while (!inStream.eof()) { // read byte from source unsigned char dataByte; inStream.read((char *)&dataByte, 1); // check if we have actually read something if (inStream.gcount() != 1 || inStream.eof()) { // we failed to read. break the read loop and close the file. break; } // write to destination in hex with a width of 2 and '0' as padding // we do not use showbase as it doesn't work with zero values outStream << "0x" << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)dataByte; // was this the last character? if (!inStream.eof() && fileData.size > static_cast<uint64_t>(inStream.tellg())) { // no. add comma. outStream << ","; // add break after 10 bytes and add indent again if (++breakCounter % 10 == 0) { outStream << std::endl << " "; } } } // close curly braces outStream << std::endl << "};" << std::endl << std::endl; // close files if (closeOutStream) { outStream.close(); } inStream.close(); if (beVerbose) { std::cout << " - succeeded." << std::endl; } return true; } else { std::cout << "Error: Failed to open file \"" << fileData.outPath.string() << "\" for writing!" << std::endl; return false; } } else { std::cout << "Error: Failed to open file \"" << fileData.inPath.string() << "\" for reading!" << std::endl; return false; } } else { std::cout << "Error: File \"" << fileData.inPath.string() << "\" does not exist!" << std::endl; } return false; }
pDevDesc ide_device::create_file_device(const std::string& device_type, const std::tr2::sys::path& filename, double width, double height) { auto expr = boost::format("%1%(filename='%2%', width=%3%, height=%4%)") % device_type % filename.generic_string() % width % height; // Create the file device via the public R API ParseStatus ps; auto result = rhost::eval::r_try_eval_str(expr.str(), R_GlobalEnv, ps); if (result.has_error) { throw rhost::util::r_error(result.error.c_str()); } pDevDesc dev_desc = nullptr; // Retrieve the device descriptor of the current device (the one created above) rhost::util::errors_to_exceptions([&] { int device_num = Rf_curDevice(); pGEDevDesc ge_dev_desc = GEgetDevice(device_num); dev_desc = ge_dev_desc->dev; }); return dev_desc; }