Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
bool readArguments(int argc, const char * argv[])
{
	bool pastFiles = false;
	for (int i = 1; i < argc; ++i)
	{
		// read argument from list
		std::string argument = argv[i];
		// check what it is
		if (argument == "-a")
		{
			if (!commonHeaderFilePath.empty() || !utilitiesFilePath.empty())
			{
				std::cout << "Error: Option -a can not be combined with -h or -u!" << std::endl;
				return false;
			}
			else if (createBinary)
			{
				std::cout << "Error: Option -a can not be combined with -b!" << std::endl;
				return false;
			}
			else if (combineResults)
			{
				std::cout << "Error: Option -a can not be combined with -1!" << std::endl;
				return false;
			}
			appendFile = true;
			pastFiles = true;
		}
		else if (argument == "-1")
		{
			// -u must be used for this to work. check if specified
			for (int j = 1; j < argc; ++j)
			{
				// read argument from list
				std::string argument = argv[j];
				if (argument == "-u")
				{
					combineResults = true;
					pastFiles = true;
					break;
				}
			}
			if (!combineResults)
			{
				// -u not specified. complain to user.
				std::cout << "Error: Option -1 has to be combined with -u!" << std::endl;
				return false;
			}
		}
		else if (argument == "-b")
		{
			if (!commonHeaderFilePath.empty() || !utilitiesFilePath.empty())
			{
				std::cout << "Error: Option -b can not be combined with -h or -u!" << std::endl;
				return false;
			}
			else if (appendFile)
			{
				std::cout << "Error: Option -b can not be combined with -a!" << std::endl;
				return false;
			}
			else if (combineResults)
			{
				std::cout << "Warning: Creating binary archive. Option -1 ignored!" << std::endl;
				return false;
			}
			createBinary = true;
			pastFiles = true;
		}
		else if (argument == "-c")
		{
			useC = true;
			pastFiles = true;
		}
		else if (argument == "-s")
		{
			useRecursion = true;
			pastFiles = true;
		}
		else if (argument == "-v")
		{
			beVerbose = true;
			pastFiles = true;
		}
		else if (argument == "-h")
		{
			if (createBinary)
			{
				std::cout << "Error: Option -h can not be combined with -b!" << std::endl;
				return false;
			}
			else if (appendFile)
			{
				std::cout << "Error: Option -h can not be combined with -a!" << std::endl;
				return false;
			}
			// try getting next argument as header file name
			i++;
			if (i < argc && argv[i] != nullptr)
			{
				if (!makeCanonical(commonHeaderFilePath, FS_NAMESPACE::path(argv[i])))
				{
					return false;
				}
			}
			else
			{
				std::cout << "Error: Option -h specified, but no file name found!" << std::endl;
				return false;
			}
			pastFiles = true;
		}
		else if (argument == "-u")
		{
			if (createBinary)
			{
				std::cout << "Error: Option -u can not be combined with -b!" << std::endl;
				return false;
			}
			else if (appendFile)
			{
				std::cout << "Error: Option -u can not be combined with -a!" << std::endl;
				return false;
			}
			// try getting next argument as utility file name
			i++;
			if (i < argc && argv[i] != nullptr)
			{
				if (!makeCanonical(utilitiesFilePath, FS_NAMESPACE::path(argv[i])))
				{
					return false;
				}
			}
			else
			{
				std::cout << "Error: Option -u specified, but no file name found!" << std::endl;
				return false;
			}
			if (!utilitiesFilePath.empty() && commonHeaderFilePath.empty())
			{
				std::cout << "Warning: -u does not make much sense without -h..." << std::endl;
			}
			pastFiles = true;
		}
		// none of the options was matched until here...
		else if (!pastFiles)
		{
			// if no files/directories have been found yet this is probably a file/directory
			if (inFilePath.empty())
			{
				if (!makeCanonical(inFilePath, FS_NAMESPACE::path(argument)))
				{
					return false;
				}
			}
			else if (outFilePath.empty())
			{
				if (!makeCanonical(outFilePath, FS_NAMESPACE::path(argument)))
				{
					return false;
				}
				pastFiles = true;
			}
		}
		else
		{
			std::cout << "Error: Unknown argument \"" << argument << "\"!" << std::endl;
			return false;
		}
	}
	return true;
}