diff --git a/CHANGES b/CHANGES index 3383d2d..8f89842 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ Changes for 3.1.0: +* Fixed issue #63: Context class redesign. Move arguments handling into a Context class. * Fixed issue #64: Remove build artifacts of samples from installation packages. +* Fixed issue #72: Move the code FileManager class generation code into its own IGenerator implementation. Changes for 3.0.1: diff --git a/src/bin2cpp/ArrayGenerator.cpp b/src/bin2cpp/ArrayGenerator.cpp index c585552..0ed05f0 100644 --- a/src/bin2cpp/ArrayGenerator.cpp +++ b/src/bin2cpp/ArrayGenerator.cpp @@ -50,12 +50,12 @@ namespace bin2cpp bool ArrayGenerator::createCppSourceFile(const char * cpp_file_path) { //check if input file exists - FILE * input = fopen(getInputFilePath(), "rb"); + FILE * input = fopen(mContext.inputFilePath.c_str(), "rb"); if (!input) return false; //Uppercase function identifier - std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mFunctionIdentifier); + std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(getContext().functionIdentifier); //Build header and cpp file path std::string headerPath = getHeaderFilePath(cpp_file_path); @@ -71,7 +71,7 @@ namespace bin2cpp //determine file properties uint32_t fileSize = ra::filesystem::GetFileSize(input); - std::string filename = ra::filesystem::GetFilename(getInputFilePath()); + std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); //Build class name std::string className = getClassName(); @@ -81,12 +81,12 @@ namespace bin2cpp //write cpp file heading fprintf(cpp, "%s", getHeaderTemplate().c_str()); - fprintf(cpp, "#include \"%s\"\n", getHeaderFilename() ); + fprintf(cpp, "#include \"%s\"\n", mContext.headerFilename.c_str() ); fprintf(cpp, "#include \n"); fprintf(cpp, "#include //for ofstream\n"); - fprintf(cpp, "namespace %s\n", mNamespace.c_str()); + fprintf(cpp, "namespace %s\n", getContext().codeNamespace.c_str()); fprintf(cpp, "{\n"); - fprintf(cpp, " class %s : public virtual %s::%s\n", className.c_str(), mNamespace.c_str(), mBaseClass.c_str()); + fprintf(cpp, " class %s : public virtual %s::%s\n", className.c_str(), getContext().codeNamespace.c_str(), getContext().baseClass.c_str()); fprintf(cpp, " {\n"); fprintf(cpp, " public:\n"); fprintf(cpp, " %s() {}\n", className.c_str()); @@ -100,13 +100,13 @@ namespace bin2cpp //create buffer for each chunks from input buffer int numLinePrinted = 0; - unsigned char * buffer = new unsigned char[mChunkSize]; + unsigned char * buffer = new unsigned char[getContext().chunkSize]; while(!feof(input)) { //read a chunk of the file - size_t readSize = fread(buffer, 1, mChunkSize, input); + size_t readSize = fread(buffer, 1, getContext().chunkSize, input); - bool isLastChunk = !(readSize == mChunkSize); + bool isLastChunk = !(readSize == getContext().chunkSize); if (readSize > 0) { @@ -136,13 +136,13 @@ namespace bin2cpp fprintf(cpp, " }\n"); fprintf(cpp, "%s", getSaveMethodTemplate().c_str()); fprintf(cpp, " };\n"); - fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", mBaseClass.c_str(), getterFunctionName.c_str(), className.c_str()); - if (isRegisterFileEnabled()) + fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", getContext().baseClass.c_str(), getterFunctionName.c_str(), className.c_str()); + if (mContext.registerFiles) { std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); fprintf(cpp, "%s", fileManagerTemplate.c_str()); } - fprintf(cpp, "}; //%s\n", mNamespace.c_str()); + fprintf(cpp, "}; //%s\n", getContext().codeNamespace.c_str()); fclose(input); fclose(cpp); @@ -153,7 +153,7 @@ namespace bin2cpp bool ArrayGenerator::printFileContent() { //check if input file exists - FILE * input = fopen(getInputFilePath(), "rb"); + FILE * input = fopen(mContext.inputFilePath.c_str(), "rb"); if (!input) return false; @@ -162,13 +162,13 @@ namespace bin2cpp //create buffer for each chunks from input buffer int numLinePrinted = 0; - unsigned char * buffer = new unsigned char[mChunkSize]; + unsigned char * buffer = new unsigned char[getContext().chunkSize]; while(!feof(input)) { //read a chunk of the file - size_t readSize = fread(buffer, 1, mChunkSize, input); + size_t readSize = fread(buffer, 1, getContext().chunkSize, input); - bool isLastChunk = !(readSize == mChunkSize); + bool isLastChunk = !(readSize == getContext().chunkSize); if (readSize > 0) { diff --git a/src/bin2cpp/BaseGenerator.cpp b/src/bin2cpp/BaseGenerator.cpp index f477ccf..46d0c19 100755 --- a/src/bin2cpp/BaseGenerator.cpp +++ b/src/bin2cpp/BaseGenerator.cpp @@ -37,9 +37,7 @@ namespace bin2cpp { - BaseGenerator::BaseGenerator() : - mCppEncoder(IGenerator::CPP_ENCODER_OCT), - mManagerEnabled(false) + BaseGenerator::BaseGenerator() { } @@ -47,111 +45,14 @@ namespace bin2cpp { } - void BaseGenerator::setInputFilePath(const char * path) + void BaseGenerator::setContext(const Context& c) { - if (path) - mInputFilePath = path; + mContext = c; } - const char * BaseGenerator::getInputFilePath() const + const Context& BaseGenerator::getContext() const { - return mInputFilePath.c_str(); - } - - void BaseGenerator::setHeaderFilename(const char * path) - { - if (path) - mHeaderFilename = path; - } - - const char * BaseGenerator::getHeaderFilename() const - { - return mHeaderFilename.c_str(); - } - - void BaseGenerator::setFunctionIdentifier(const char * function_identifier) - { - if (function_identifier) - mFunctionIdentifier = function_identifier; - } - - const char * BaseGenerator::getFunctionIdentifier() const - { - return mFunctionIdentifier.c_str(); - } - - void BaseGenerator::setReportedFilePath(const char * path) - { - if (path) - mReportedFilePath = path; - } - - const char * BaseGenerator::getReportedFilePath() const - { - return mReportedFilePath.c_str(); - } - - void BaseGenerator::setChunkSize(size_t chunk_size) - { - mChunkSize = chunk_size; - } - - size_t BaseGenerator::getChunkSize() const - { - return mChunkSize; - } - - void BaseGenerator::setNamespace(const char * name) - { - if (name) - mNamespace = name; - } - - const char * BaseGenerator::getNamespace() const - { - return mNamespace.c_str(); - } - - void BaseGenerator::setBaseClass(const char * name) - { - if (name) - mBaseClass = name; - } - - const char * BaseGenerator::getBaseClass() const - { - return mBaseClass.c_str(); - } - - void BaseGenerator::setCppEncoder(const IGenerator::CppEncoderEnum & cpp_encoder) - { - mCppEncoder = cpp_encoder; - } - - IGenerator::CppEncoderEnum BaseGenerator::getCppEncoder() const - { - return mCppEncoder; - } - - void BaseGenerator::setManagerHeaderFilename(const char * manager_file) - { - if (manager_file) - mManagerHeaderFilename = manager_file; - } - - const char * BaseGenerator::getManagerHeaderFilename() const - { - return mManagerHeaderFilename.c_str(); - } - - void BaseGenerator::setRegisterFileEnabled(bool register_file_enabled) - { - mManagerEnabled = register_file_enabled; - } - - bool BaseGenerator::isRegisterFileEnabled() const - { - return mManagerEnabled; + return mContext; } //------------------------------- @@ -161,7 +62,7 @@ namespace bin2cpp std::string BaseGenerator::getGetterFunctionName() { //Uppercase function identifier - std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mFunctionIdentifier); + std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mContext.functionIdentifier); std::string getter; getter.append("get"); @@ -201,8 +102,8 @@ namespace bin2cpp header << " * bin2cpp is open source software, see http://github.com/end2endzone/bin2cpp\n"; if (include_source_file) { - std::string filename = ra::filesystem::GetFilename(mInputFilePath.c_str()); - uint64_t lastModifiedDate = ra::filesystem::GetFileModifiedDate(mInputFilePath); + std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); + uint64_t lastModifiedDate = ra::filesystem::GetFileModifiedDate(mContext.inputFilePath); header << " * Source code for file '" << filename << "', last modified " << lastModifiedDate << ".\n"; } header << " * Do not modify this file.\n"; @@ -228,22 +129,22 @@ namespace bin2cpp std::string BaseGenerator::getFileManagerRegistrationTemplate() { - if (!this->isRegisterFileEnabled()) + if (!mContext.registerFiles) return std::string(); //Build class name std::string className = getClassName(); std::string output; - output << " typedef const " << mBaseClass << " & (*t_func)();\n"; + output << " typedef const " << mContext.baseClass << " & (*t_func)();\n"; output << " extern bool RegisterFile(t_func iFunctionPointer);\n"; - output << " static bool k" << className << "Registered = " << mNamespace << "::RegisterFile(&" << getGetterFunctionName() << ");\n"; + output << " static bool k" << className << "Registered = " << mContext.codeNamespace << "::RegisterFile(&" << getGetterFunctionName() << ");\n"; return output; } std::string BaseGenerator::getClassName() { - std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mFunctionIdentifier); + std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mContext.functionIdentifier); std::string className; className.append(functionIdentifier.c_str()); className.append("File"); @@ -252,7 +153,7 @@ namespace bin2cpp std::string BaseGenerator::getClassMacroGuardPrefix() { - std::string macroGuardPrefix = ra::strings::Uppercase(mNamespace); + std::string macroGuardPrefix = ra::strings::Uppercase(mContext.codeNamespace); //remove namespace separators ra::strings::Replace(macroGuardPrefix, "::", "_"); @@ -264,13 +165,13 @@ namespace bin2cpp { std::string output; - std::string inputFileName = ra::filesystem::GetFilename(getInputFilePath()); + std::string inputFileName = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); //could we report getFileName() as a substring of getFilePath() ? - const char * reported_path = getReportedFilePath(); + const char * reported_path = mContext.reportedFilePath.c_str(); if (reported_path != NULL && reported_path[0] != '\0') { - size_t offset = mReportedFilePath.find(inputFileName); + size_t offset = mContext.reportedFilePath.find(inputFileName); if (offset != std::string::npos) { output = "return &getFilePath()["; @@ -292,7 +193,7 @@ namespace bin2cpp std::string output; //convert mReportedFilePath string to c++ - std::string path = mReportedFilePath; + std::string path = mContext.reportedFilePath; #ifdef _WIN32 //escape backslash characters for c++ static const std::string BACKSLASH = "\\"; @@ -301,7 +202,7 @@ namespace bin2cpp #endif //is there a reported path specified ? - const char * reported_path = getReportedFilePath(); + const char * reported_path = mContext.reportedFilePath.c_str(); if (reported_path != NULL && reported_path[0] != '\0') { output = "return \""; @@ -342,59 +243,11 @@ namespace bin2cpp fprintf(header, "\n"); fprintf(header, "#include \n"); fprintf(header, "\n"); - fprintf(header, "namespace %s\n", mNamespace.c_str()); - fprintf(header, "{\n"); - fprintf(header, " #ifndef %s_EMBEDDEDFILE_CLASS\n", classMacroGuardPrefix.c_str()); - fprintf(header, " #define %s_EMBEDDEDFILE_CLASS\n", classMacroGuardPrefix.c_str()); - fprintf(header, " class %s\n", mBaseClass.c_str()); - fprintf(header, " {\n"); - fprintf(header, " public:\n"); - fprintf(header, " virtual size_t getSize() const = 0;\n"); - fprintf(header, " /* DEPRECATED */ virtual inline const char * getFilename() const { return getFileName(); }\n"); - fprintf(header, " virtual const char * getFileName() const = 0;\n"); - fprintf(header, " virtual const char * getFilePath() const = 0;\n"); - fprintf(header, " virtual const char * getBuffer() const = 0;\n"); - fprintf(header, " virtual bool save(const char * filename) const = 0;\n"); - fprintf(header, " };\n"); - fprintf(header, " #endif //%s_EMBEDDEDFILE_CLASS\n", classMacroGuardPrefix.c_str()); - fprintf(header, " const %s & %s();\n", mBaseClass.c_str(), getGetterFunctionName().c_str()); - fprintf(header, "}; //%s\n", mNamespace.c_str()); - fprintf(header, "\n"); - fprintf(header, "#endif //%s\n", macroGuard.c_str()); - - fclose(header); - - return true; - } - - bool BaseGenerator::createManagerHeaderFile(const char * header_file_path) - { - FILE * header = fopen(header_file_path, "w"); - if (!header) - return false; - - //define macro guard a macro matching the filename - std::string macroGuard; - macroGuard += getCppIncludeGuardMacroName(mNamespace.c_str()); //prefix the custom namespace for the file manager - if (!macroGuard.empty()) - macroGuard += "_"; - macroGuard += getCppIncludeGuardMacroName(header_file_path); - - std::string classMacroGuardPrefix = getClassMacroGuardPrefix(); - std::string fileHeader = getHeaderTemplate(false); - - fprintf(header, "%s", fileHeader.c_str()); - fprintf(header, "#ifndef %s\n", macroGuard.c_str()); - fprintf(header, "#define %s\n", macroGuard.c_str()); - fprintf(header, "\n"); - fprintf(header, "#include \n"); - fprintf(header, "#include \n"); - fprintf(header, "\n"); - fprintf(header, "namespace %s\n", mNamespace.c_str()); + fprintf(header, "namespace %s\n", mContext.codeNamespace.c_str()); fprintf(header, "{\n"); fprintf(header, " #ifndef %s_EMBEDDEDFILE_CLASS\n", classMacroGuardPrefix.c_str()); fprintf(header, " #define %s_EMBEDDEDFILE_CLASS\n", classMacroGuardPrefix.c_str()); - fprintf(header, " class %s\n", mBaseClass.c_str()); + fprintf(header, " class %s\n", mContext.baseClass.c_str()); fprintf(header, " {\n"); fprintf(header, " public:\n"); fprintf(header, " virtual size_t getSize() const = 0;\n"); @@ -405,28 +258,8 @@ namespace bin2cpp fprintf(header, " virtual bool save(const char * filename) const = 0;\n"); fprintf(header, " };\n"); fprintf(header, " #endif //%s_EMBEDDEDFILE_CLASS\n", classMacroGuardPrefix.c_str()); - fprintf(header, "\n"); - fprintf(header, " #ifndef %s_FILEMANAGER_CLASS\n", classMacroGuardPrefix.c_str()); - fprintf(header, " #define %s_FILEMANAGER_CLASS\n", classMacroGuardPrefix.c_str()); - fprintf(header, " class FileManager\n"); - fprintf(header, " {\n"); - fprintf(header, " private:\n"); - fprintf(header, " FileManager();\n"); - fprintf(header, " ~FileManager();\n"); - fprintf(header, " public:\n"); - fprintf(header, " typedef const %s & (*t_func)();\n", mBaseClass.c_str()); - fprintf(header, " static FileManager & getInstance();\n"); - fprintf(header, " void registerFile(t_func func);\n"); - fprintf(header, " size_t getFileCount() const;\n"); - fprintf(header, " const %s * getFile(const size_t & index) const;\n", mBaseClass.c_str()); - fprintf(header, " bool saveFiles(const char * directory) const;\n"); - fprintf(header, " bool createParentDirectories(const char * file_path) const;\n"); - fprintf(header, " bool createDirectories(const char * path) const;\n"); - fprintf(header, " private:\n"); - fprintf(header, " std::vector functions_;\n"); - fprintf(header, " };\n"); - fprintf(header, " #endif //%s_FILEMANAGER_CLASS\n", classMacroGuardPrefix.c_str()); - fprintf(header, "}; //%s\n", mNamespace.c_str()); + fprintf(header, " const %s & %s();\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); + fprintf(header, "}; //%s\n", mContext.codeNamespace.c_str()); fprintf(header, "\n"); fprintf(header, "#endif //%s\n", macroGuard.c_str()); @@ -435,136 +268,10 @@ namespace bin2cpp return true; } - bool BaseGenerator::createManagerSourceFile(const char * cpp_file_path) - { - FILE * cpp = fopen(cpp_file_path, "w"); - if (!cpp) - return false; - - //Build header and cpp file path - std::string headerPath = getHeaderFilePath(cpp_file_path); - std::string cppPath = cpp_file_path; - - std::string fileHeader = getHeaderTemplate(false); - - fprintf(cpp, "%s", fileHeader.c_str()); - fprintf(cpp, "#include \"%s\"\n", getManagerHeaderFilename()); - fprintf(cpp, "#include \n"); - fprintf(cpp, "#include // strlen\n"); - fprintf(cpp, "#include // stat\n"); - fprintf(cpp, "#include // errno, EEXIST\n"); - fprintf(cpp, "#if defined(_WIN32)\n"); - fprintf(cpp, "#include // _mkdir\n"); - fprintf(cpp, "#endif\n"); - fprintf(cpp, "\n"); - fprintf(cpp, "#if defined(_WIN32)\n"); - fprintf(cpp, "#define portable_stat _stat\n"); - fprintf(cpp, "#define portable_mkdir(path) _mkdir(path)\n"); - fprintf(cpp, "#define PATH_SEPARATOR_CHAR '\\\\'\n"); - fprintf(cpp, "#define PATH_SEPARATOR_STR \"\\\\\"\n"); - fprintf(cpp, "#else\n"); - fprintf(cpp, "#define portable_stat stat\n"); - fprintf(cpp, "#define portable_mkdir(path) mkdir(path, 0755)\n"); - fprintf(cpp, "#define PATH_SEPARATOR_CHAR '/'\n"); - fprintf(cpp, "#define PATH_SEPARATOR_STR \"/\"\n"); - fprintf(cpp, "#endif\n"); - fprintf(cpp, "\n"); - fprintf(cpp, "namespace %s\n", mNamespace.c_str()); - fprintf(cpp, "{\n"); - fprintf(cpp, " bool RegisterFile(FileManager::t_func functionPointer)\n"); - fprintf(cpp, " {\n"); - fprintf(cpp, " if (functionPointer == NULL)\n"); - fprintf(cpp, " return false;\n"); - fprintf(cpp, " FileManager::getInstance().registerFile(functionPointer);\n"); - fprintf(cpp, " return true;\n"); - fprintf(cpp, " }\n"); - fprintf(cpp, " FileManager::FileManager() {}\n"); - fprintf(cpp, " FileManager::~FileManager() {}\n"); - fprintf(cpp, " FileManager & FileManager::getInstance() { static FileManager _mgr; return _mgr; }\n"); - fprintf(cpp, " void FileManager::registerFile(t_func func) { functions_.push_back(func); }\n"); - fprintf(cpp, " size_t FileManager::getFileCount() const { return functions_.size(); }\n"); - fprintf(cpp, " const File * FileManager::getFile(const size_t & index) const\n"); - fprintf(cpp, " {\n"); - fprintf(cpp, " if (index >= functions_.size())\n"); - fprintf(cpp, " return NULL;\n"); - fprintf(cpp, " t_func ressource_getter_function = functions_[index];\n"); - fprintf(cpp, " const %s::File & resource = ressource_getter_function();\n", mNamespace.c_str()); - fprintf(cpp, " return &resource;\n"); - fprintf(cpp, " }\n"); - fprintf(cpp, " bool FileManager::saveFiles(const char * directory) const\n"); - fprintf(cpp, " {\n"); - fprintf(cpp, " if (directory == NULL)\n"); - fprintf(cpp, " return false;\n"); - fprintf(cpp, " size_t count = getFileCount();\n"); - fprintf(cpp, " for(size_t i=0; igetFilePath());\n"); - fprintf(cpp, " if (!createParentDirectories(path.c_str()))\n"); - fprintf(cpp, " return false;\n"); - fprintf(cpp, " bool saved = f->save(path.c_str());\n"); - fprintf(cpp, " if (!saved)\n"); - fprintf(cpp, " return false;\n"); - fprintf(cpp, " }\n"); - fprintf(cpp, " return true;\n"); - fprintf(cpp, " }\n"); - fprintf(cpp, " static inline bool isRootDirectory(const char * path)\n"); - fprintf(cpp, " {\n"); - fprintf(cpp, " if (path == NULL && path[0] == '\\0')\n"); - fprintf(cpp, " return false;\n"); - fprintf(cpp, " #if defined(_WIN32)\n"); - fprintf(cpp, " bool isDriveLetter = ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'));\n"); - fprintf(cpp, " if ((isDriveLetter && path[1] == ':' && path[2] == '\\0') || // test for C:\n"); - fprintf(cpp, " (isDriveLetter && path[1] == ':' && path[2] == PATH_SEPARATOR_CHAR && path[3] == '\\0')) // test for C:\\ \n"); - fprintf(cpp, " return true;\n"); - fprintf(cpp, " #else\n"); - fprintf(cpp, " if (path[0] == PATH_SEPARATOR_CHAR)\n"); - fprintf(cpp, " return true;\n"); - fprintf(cpp, " #endif\n"); - fprintf(cpp, " return false;\n"); - fprintf(cpp, " }\n"); - fprintf(cpp, " bool FileManager::createParentDirectories(const char * file_path) const\n"); - fprintf(cpp, " {\n"); - fprintf(cpp, " if (file_path == NULL)\n"); - fprintf(cpp, " return false;\n"); - fprintf(cpp, " std::string accumulator;\n"); - fprintf(cpp, " size_t length = strlen(file_path);\n"); - fprintf(cpp, " for(size_t i=0; i 0) { @@ -591,12 +298,12 @@ namespace bin2cpp //output std::string text; - switch(mCppEncoder) + switch(mContext.cppEncoder) { - case IGenerator::CPP_ENCODER_HEX: + case CPP_ENCODER_HEX: text = ra::code::cpp::ToHexString(buffer, readSize); break; - case IGenerator::CPP_ENCODER_OCT: + case CPP_ENCODER_OCT: default: text = ra::code::cpp::ToOctString(buffer, readSize, false); break; diff --git a/src/bin2cpp/BaseGenerator.h b/src/bin2cpp/BaseGenerator.h index 33db9cd..0fcfd6e 100644 --- a/src/bin2cpp/BaseGenerator.h +++ b/src/bin2cpp/BaseGenerator.h @@ -40,31 +40,11 @@ namespace bin2cpp virtual ~BaseGenerator(); //IGenerator methods - virtual void setInputFilePath(const char * path); - virtual const char * getInputFilePath() const; - virtual void setHeaderFilename(const char * path); - virtual const char * getHeaderFilename() const; - virtual void setFunctionIdentifier(const char * function_identifier); - virtual const char * getFunctionIdentifier() const; - virtual void setReportedFilePath(const char * path); - virtual const char * getReportedFilePath() const; - virtual void setChunkSize(size_t chunk_size); - virtual size_t getChunkSize() const; - virtual void setNamespace(const char * name); - virtual const char * getNamespace() const; - virtual void setBaseClass(const char * name); - virtual const char * getBaseClass() const; - virtual void setCppEncoder(const CppEncoderEnum & cpp_encoder); - virtual CppEncoderEnum getCppEncoder() const; - virtual void setManagerHeaderFilename(const char * manager_file); - virtual const char * getManagerHeaderFilename() const; - virtual void setRegisterFileEnabled(bool register_file_enabled); - virtual bool isRegisterFileEnabled() const; + virtual void setContext(const Context& c); + virtual const Context & getContext() const; //same header file for all generators virtual bool createCppHeaderFile(const char * header_file_path); - virtual bool createManagerHeaderFile(const char * header_file_path); - virtual bool createManagerSourceFile(const char * cpp_file_path); virtual bool printFileContent(); protected: @@ -82,16 +62,7 @@ namespace bin2cpp virtual std::string getImplOfGetFilePath(); //attributes - std::string mInputFilePath; - std::string mHeaderFilename; - std::string mReportedFilePath; - std::string mFunctionIdentifier; - size_t mChunkSize; - std::string mNamespace; - std::string mBaseClass; - std::string mManagerHeaderFilename; - IGenerator::CppEncoderEnum mCppEncoder; - bool mManagerEnabled; + Context mContext; }; }; //bin2cpp diff --git a/src/bin2cpp/CMakeLists.txt b/src/bin2cpp/CMakeLists.txt index d3689e1..fffb214 100644 --- a/src/bin2cpp/CMakeLists.txt +++ b/src/bin2cpp/CMakeLists.txt @@ -15,10 +15,15 @@ add_executable(bin2cpp bin2cpp.samples.txt common.cpp common.h + Context.cpp + Context.h crc32.cpp crc32.h + enums.h IGenerator.h main.cpp + ManagerGenerator.cpp + ManagerGenerator.h SegmentGenerator.cpp SegmentGenerator.h StringGenerator.cpp diff --git a/src/bin2cpp/Context.cpp b/src/bin2cpp/Context.cpp new file mode 100644 index 0000000..ba8f69e --- /dev/null +++ b/src/bin2cpp/Context.cpp @@ -0,0 +1,103 @@ +/********************************************************************************** + * MIT License + * + * Copyright (c) 2018 Antoine Beauchamp + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *********************************************************************************/ + +#include "Context.h" + +namespace bin2cpp +{ + Context::Context() + { + reset(); + } + + Context::Context(const Context& other) + { + (*this) = other; + } + + Context::~Context() + { + } + + Context& Context::operator=(const Context& other) + { + if ( this != &other ) + { + this->hasInputFile = other.hasInputFile ; + this->hasInputDir = other.hasInputDir ; + this->hasOutputDir = other.hasOutputDir ; + this->hasReportedFilePath = other.hasReportedFilePath ; + this->hasManagerFile = other.hasManagerFile ; + this->keepDirectoryStructure = other.keepDirectoryStructure ; + this->overrideExistingFiles = other.overrideExistingFiles ; + this->registerFiles = other.registerFiles ; + this->plainOutput = other.plainOutput ; + this->inputFilePath = other.inputFilePath ; + this->inputDirPath = other.inputDirPath ; + this->outputDirPath = other.outputDirPath ; + this->headerFilename = other.headerFilename ; + this->functionIdentifier = other.functionIdentifier ; + this->reportedFilePath = other.reportedFilePath ; + this->chunkSize = other.chunkSize ; + this->codeNamespace = other.codeNamespace ; + this->baseClass = other.baseClass ; + this->managerHeaderFilename = other.managerHeaderFilename ; + this->cppEncoder = other.cppEncoder ; + this->generatorName = other.generatorName ; + } + return *this; + } + + void Context::reset() + { + hasInputFile = false; + hasInputDir = false; + hasOutputDir = false; + hasReportedFilePath = false; + hasManagerFile = false; + keepDirectoryStructure = false; + overrideExistingFiles = false; + registerFiles = false; + plainOutput = false; + + inputFilePath.clear(); + inputDirPath.clear(); + outputDirPath.clear(); + headerFilename.clear(); + functionIdentifier.clear(); + reportedFilePath.clear(); + chunkSize = 0; + codeNamespace.clear(); + baseClass.clear(); + managerHeaderFilename.clear(); + cppEncoder = CppEncoderEnum::CPP_ENCODER_HEX; + generatorName.clear(); + } + + //------------------------------- + //protected methods + //------------------------------- + + +}; //bin2cpp \ No newline at end of file diff --git a/src/bin2cpp/Context.h b/src/bin2cpp/Context.h new file mode 100644 index 0000000..d17ac1b --- /dev/null +++ b/src/bin2cpp/Context.h @@ -0,0 +1,81 @@ +/********************************************************************************** + * MIT License + * + * Copyright (c) 2018 Antoine Beauchamp + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *********************************************************************************/ + +#ifndef CONTEXT_H +#define CONTEXT_H + +#include +#include "enums.h" + +namespace bin2cpp +{ + + /// + ///This is the command line context for generating code. + /// + class Context + { + public: + Context(); + Context(const Context & other); + virtual ~Context(); + + Context& operator=(const Context& other); + + // flags + bool hasInputFile; // true if 'inputFilePath' is set. + bool hasInputDir; // true if 'inputDirPath' is set. + bool hasOutputDir; // true if 'outputDirPath' is set. + bool hasReportedFilePath; // true if 'reportedFilePath' is set. + bool hasManagerFile; // true if 'managerHeaderFilename' is set. + bool keepDirectoryStructure; // true if the output files must have the same directory structure as the input files. Valid only when --dir is used. + bool overrideExistingFiles; + bool registerFiles; + bool plainOutput; + + // public attributes + std::string inputFilePath; // The path of the input file (resource) to embeded as C++ source code. + std::string inputDirPath; + std::string outputDirPath; + std::string headerFilename; // The path of the input file (resource) to embeded as C++ source code. + std::string functionIdentifier; + std::string reportedFilePath; // path reported in the public api when calling getFilePath(); + size_t chunkSize; + std::string codeNamespace; + std::string baseClass; + std::string managerHeaderFilename; + CppEncoderEnum cppEncoder; + std::string generatorName; + + void reset(); + + protected: + + //attributes + + }; + +}; //bin2cpp + +#endif //BASEGENERATOR_H diff --git a/src/bin2cpp/IGenerator.h b/src/bin2cpp/IGenerator.h index b99e22d..d7b487e 100644 --- a/src/bin2cpp/IGenerator.h +++ b/src/bin2cpp/IGenerator.h @@ -26,6 +26,7 @@ #define IGENERATOR_H #include +#include "Context.h" namespace bin2cpp { @@ -35,140 +36,16 @@ namespace bin2cpp public: /// - ///Get the name of the generator. + ///Sets the current context for the generator. /// - ///Returns the name of the generator - virtual const char * getName() const = 0; + ///The new context. + virtual void setContext(const Context& c) = 0; /// - ///Defines the path of the binary input file. + ///Get the current context set for the generator. /// - ///The path of the input file (resource) to embeded as C++ source code. - virtual void setInputFilePath(const char * path) = 0; - - /// - ///Provides the path of the binary input file. - /// - ///Returns the path of the binary input file. Returns an empty string if not defined. - virtual const char * getInputFilePath() const = 0; - - /// - ///Defines the filename of the generated header. - /// - ///The path of the input file (resource) to embeded as C++ source code. - virtual void setHeaderFilename(const char * path) = 0; - - /// - ///Provides the filename of the generated header. - /// - ///Returns the path of the binary input file. Returns an empty string if not defined. - virtual const char * getHeaderFilename() const = 0; - - /// - ///Defines the unique identifier name for the File class getter function. - /// - ///The unique identifier name for the File class getter function. - virtual void setFunctionIdentifier(const char * function_identifier) = 0; - - /// - ///Provides the unique identifier name for the File class getter function. - /// - ///Returns the unique identifier name for the File class getter function. Returns an empty string if not defined. - virtual const char * getFunctionIdentifier() const = 0; - - /// - ///Defines the path reported by the getFilePath() method of the File class. - /// - ///The path of the input file (resource) to embeded as C++ source code. - virtual void setReportedFilePath(const char * path) = 0; - - /// - ///Provides the path reported by the getFilePath() method of the File class. - /// - ///The path reported by the getFilePath() method of the File class. Returns an empty string if not defined. - virtual const char * getReportedFilePath() const = 0; - - /// - ///Defines the size in bytes of each chunk of data. - /// - ///The size in bytes of each chunk of data. - virtual void setChunkSize(size_t chunk_size) = 0; - - /// - ///Provides the size in bytes of each chunk of data. - /// - ///Returns the unique identifier name for the File class getter function. Returns an empty string if not defined. - virtual size_t getChunkSize() const = 0; - - /// - ///Defines the namespace of the generated code. - /// - ///The name of the namespace of the generated code. - virtual void setNamespace(const char * name) = 0; - - /// - ///Provides the namespace of the generated code. - /// - ///Returns the name of the namespace of the generated code. Returns an empty string if not defined. - virtual const char * getNamespace() const = 0; - - /// - ///Defines the base class of the generated code. - /// - ///The name of the base class of the generated code. - virtual void setBaseClass(const char * name) = 0; - - /// - ///Provides the base class of the generated code. - /// - ///Returns the name of the base class of the generated code. Returns an empty string if not defined. - virtual const char * getBaseClass() const = 0; - - /// - ///Defines the filename of the FileManager generated header. - /// - ///The path of the FileManager output file. - virtual void setManagerHeaderFilename(const char * path) = 0; - - /// - ///Provides the filename of the FileManager generated header. - /// - ///Returns the path of the FileManager output file. Returns an empty string if not defined. - virtual const char * getManagerHeaderFilename() const = 0; - - /// - ///Enable or disable the registration of the generated file to the FileManager. - /// - ///The new value of the flag. - virtual void setRegisterFileEnabled(bool register_file_enabled) = 0; - - /// - ///Returns true if the generated file should be registated FileManager should be used in generated code. - /// - ///Returns true if the FileManager should be used in generated code. Returns false otherwise. - virtual bool isRegisterFileEnabled() const = 0; - - /// - ///Defines the different type of cpp encoding. - ///See setCppEncoder() and getCppEncoder() functions. - /// - enum CppEncoderEnum - { - CPP_ENCODER_OCT, - CPP_ENCODER_HEX, - }; - - /// - ///Defines the type of cpp encoder to use. See CppEncoderEnum for details. - /// - ///The type of cpp encoder to use - virtual void setCppEncoder(const CppEncoderEnum & cpp_encoder) = 0; - - /// - ///Provides the type of cpp encoder to use. See CppEncoderEnum for details. - /// - ///Returns the type of cpp encoder to use. - virtual CppEncoderEnum getCppEncoder() const = 0; + ///Returns the current context set for the generator. + virtual const Context& getContext() const = 0; /// ///Creates a header file for embedding a given file into C++ source code. @@ -184,20 +61,6 @@ namespace bin2cpp ///Returns true when the file was created. Returns false otherwise. virtual bool createCppSourceFile(const char * cpp_file_path) = 0; - /// - ///Creates a FileManager header file. - /// - ///The path of the header file (*.h). - ///Returns true when the file was created. Returns false otherwise. - virtual bool createManagerHeaderFile(const char * header_file_path) = 0; - - /// - ///Creates a FileManager cpp file. - /// - ///The path of the cpp file (*.h). - ///Returns true when the file was created. Returns false otherwise. - virtual bool createManagerSourceFile(const char * cpp_file_path) = 0; - /// ///Print the encoded file content to stdout /// diff --git a/src/bin2cpp/ManagerGenerator.cpp b/src/bin2cpp/ManagerGenerator.cpp new file mode 100644 index 0000000..72a8126 --- /dev/null +++ b/src/bin2cpp/ManagerGenerator.cpp @@ -0,0 +1,247 @@ +/********************************************************************************** + * MIT License + * + * Copyright (c) 2018 Antoine Beauchamp + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *********************************************************************************/ + +#include "ManagerGenerator.h" +#include +#include +#include +#include + +#include "common.h" + +namespace bin2cpp +{ + ManagerGenerator::ManagerGenerator() + { + } + + ManagerGenerator::~ManagerGenerator() + { + } + + const char * ManagerGenerator::getName() const + { + return "manager"; + } + + bool ManagerGenerator::createCppHeaderFile(const char* header_file_path) + { + FILE* header = fopen(header_file_path, "w"); + if ( !header ) + return false; + + //define macro guard a macro matching the filename + std::string macroGuard; + macroGuard += getCppIncludeGuardMacroName(mContext.codeNamespace.c_str()); //prefix the custom namespace for the file manager + if ( !macroGuard.empty() ) + macroGuard += "_"; + macroGuard += getCppIncludeGuardMacroName(header_file_path); + + std::string classMacroGuardPrefix = getClassMacroGuardPrefix(); + std::string fileHeader = getHeaderTemplate(false); + + fprintf(header, "%s", fileHeader.c_str()); + fprintf(header, "#ifndef %s\n", macroGuard.c_str()); + fprintf(header, "#define %s\n", macroGuard.c_str()); + fprintf(header, "\n"); + fprintf(header, "#include \n"); + fprintf(header, "#include \n"); + fprintf(header, "\n"); + fprintf(header, "namespace %s\n", mContext.codeNamespace.c_str()); + fprintf(header, "{\n"); + fprintf(header, " #ifndef %s_EMBEDDEDFILE_CLASS\n", classMacroGuardPrefix.c_str()); + fprintf(header, " #define %s_EMBEDDEDFILE_CLASS\n", classMacroGuardPrefix.c_str()); + fprintf(header, " class %s\n", mContext.baseClass.c_str()); + fprintf(header, " {\n"); + fprintf(header, " public:\n"); + fprintf(header, " virtual size_t getSize() const = 0;\n"); + fprintf(header, " /* DEPRECATED */ virtual inline const char * getFilename() const { return getFileName(); }\n"); + fprintf(header, " virtual const char * getFileName() const = 0;\n"); + fprintf(header, " virtual const char * getFilePath() const = 0;\n"); + fprintf(header, " virtual const char * getBuffer() const = 0;\n"); + fprintf(header, " virtual bool save(const char * filename) const = 0;\n"); + fprintf(header, " };\n"); + fprintf(header, " #endif //%s_EMBEDDEDFILE_CLASS\n", classMacroGuardPrefix.c_str()); + fprintf(header, "\n"); + fprintf(header, " #ifndef %s_FILEMANAGER_CLASS\n", classMacroGuardPrefix.c_str()); + fprintf(header, " #define %s_FILEMANAGER_CLASS\n", classMacroGuardPrefix.c_str()); + fprintf(header, " class FileManager\n"); + fprintf(header, " {\n"); + fprintf(header, " private:\n"); + fprintf(header, " FileManager();\n"); + fprintf(header, " ~FileManager();\n"); + fprintf(header, " public:\n"); + fprintf(header, " typedef const %s & (*t_func)();\n", mContext.baseClass.c_str()); + fprintf(header, " static FileManager & getInstance();\n"); + fprintf(header, " void registerFile(t_func func);\n"); + fprintf(header, " size_t getFileCount() const;\n"); + fprintf(header, " const %s * getFile(const size_t & index) const;\n", mContext.baseClass.c_str()); + fprintf(header, " bool saveFiles(const char * directory) const;\n"); + fprintf(header, " bool createParentDirectories(const char * file_path) const;\n"); + fprintf(header, " bool createDirectories(const char * path) const;\n"); + fprintf(header, " private:\n"); + fprintf(header, " std::vector functions_;\n"); + fprintf(header, " };\n"); + fprintf(header, " #endif //%s_FILEMANAGER_CLASS\n", classMacroGuardPrefix.c_str()); + fprintf(header, "}; //%s\n", mContext.codeNamespace.c_str()); + fprintf(header, "\n"); + fprintf(header, "#endif //%s\n", macroGuard.c_str()); + + fclose(header); + + return true; + } + + bool ManagerGenerator::createCppSourceFile(const char* cpp_file_path) + { + FILE* cpp = fopen(cpp_file_path, "w"); + if ( !cpp ) + return false; + + //Build header and cpp file path + std::string headerPath = getHeaderFilePath(cpp_file_path); + std::string cppPath = cpp_file_path; + + std::string fileHeader = getHeaderTemplate(false); + + fprintf(cpp, "%s", fileHeader.c_str()); + fprintf(cpp, "#include \"%s\"\n", mContext.managerHeaderFilename.c_str()); + fprintf(cpp, "#include \n"); + fprintf(cpp, "#include // strlen\n"); + fprintf(cpp, "#include // stat\n"); + fprintf(cpp, "#include // errno, EEXIST\n"); + fprintf(cpp, "#if defined(_WIN32)\n"); + fprintf(cpp, "#include // _mkdir\n"); + fprintf(cpp, "#endif\n"); + fprintf(cpp, "\n"); + fprintf(cpp, "#if defined(_WIN32)\n"); + fprintf(cpp, "#define portable_stat _stat\n"); + fprintf(cpp, "#define portable_mkdir(path) _mkdir(path)\n"); + fprintf(cpp, "#define PATH_SEPARATOR_CHAR '\\\\'\n"); + fprintf(cpp, "#define PATH_SEPARATOR_STR \"\\\\\"\n"); + fprintf(cpp, "#else\n"); + fprintf(cpp, "#define portable_stat stat\n"); + fprintf(cpp, "#define portable_mkdir(path) mkdir(path, 0755)\n"); + fprintf(cpp, "#define PATH_SEPARATOR_CHAR '/'\n"); + fprintf(cpp, "#define PATH_SEPARATOR_STR \"/\"\n"); + fprintf(cpp, "#endif\n"); + fprintf(cpp, "\n"); + fprintf(cpp, "namespace %s\n", mContext.codeNamespace.c_str()); + fprintf(cpp, "{\n"); + fprintf(cpp, " bool RegisterFile(FileManager::t_func functionPointer)\n"); + fprintf(cpp, " {\n"); + fprintf(cpp, " if (functionPointer == NULL)\n"); + fprintf(cpp, " return false;\n"); + fprintf(cpp, " FileManager::getInstance().registerFile(functionPointer);\n"); + fprintf(cpp, " return true;\n"); + fprintf(cpp, " }\n"); + fprintf(cpp, " FileManager::FileManager() {}\n"); + fprintf(cpp, " FileManager::~FileManager() {}\n"); + fprintf(cpp, " FileManager & FileManager::getInstance() { static FileManager _mgr; return _mgr; }\n"); + fprintf(cpp, " void FileManager::registerFile(t_func func) { functions_.push_back(func); }\n"); + fprintf(cpp, " size_t FileManager::getFileCount() const { return functions_.size(); }\n"); + fprintf(cpp, " const File * FileManager::getFile(const size_t & index) const\n"); + fprintf(cpp, " {\n"); + fprintf(cpp, " if (index >= functions_.size())\n"); + fprintf(cpp, " return NULL;\n"); + fprintf(cpp, " t_func ressource_getter_function = functions_[index];\n"); + fprintf(cpp, " const %s::File & resource = ressource_getter_function();\n", mContext.codeNamespace.c_str()); + fprintf(cpp, " return &resource;\n"); + fprintf(cpp, " }\n"); + fprintf(cpp, " bool FileManager::saveFiles(const char * directory) const\n"); + fprintf(cpp, " {\n"); + fprintf(cpp, " if (directory == NULL)\n"); + fprintf(cpp, " return false;\n"); + fprintf(cpp, " size_t count = getFileCount();\n"); + fprintf(cpp, " for(size_t i=0; igetFilePath());\n"); + fprintf(cpp, " if (!createParentDirectories(path.c_str()))\n"); + fprintf(cpp, " return false;\n"); + fprintf(cpp, " bool saved = f->save(path.c_str());\n"); + fprintf(cpp, " if (!saved)\n"); + fprintf(cpp, " return false;\n"); + fprintf(cpp, " }\n"); + fprintf(cpp, " return true;\n"); + fprintf(cpp, " }\n"); + fprintf(cpp, " static inline bool isRootDirectory(const char * path)\n"); + fprintf(cpp, " {\n"); + fprintf(cpp, " if (path == NULL && path[0] == '\\0')\n"); + fprintf(cpp, " return false;\n"); + fprintf(cpp, " #if defined(_WIN32)\n"); + fprintf(cpp, " bool isDriveLetter = ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'));\n"); + fprintf(cpp, " if ((isDriveLetter && path[1] == ':' && path[2] == '\\0') || // test for C:\n"); + fprintf(cpp, " (isDriveLetter && path[1] == ':' && path[2] == PATH_SEPARATOR_CHAR && path[3] == '\\0')) // test for C:\\ \n"); + fprintf(cpp, " return true;\n"); + fprintf(cpp, " #else\n"); + fprintf(cpp, " if (path[0] == PATH_SEPARATOR_CHAR)\n"); + fprintf(cpp, " return true;\n"); + fprintf(cpp, " #endif\n"); + fprintf(cpp, " return false;\n"); + fprintf(cpp, " }\n"); + fprintf(cpp, " bool FileManager::createParentDirectories(const char * file_path) const\n"); + fprintf(cpp, " {\n"); + fprintf(cpp, " if (file_path == NULL)\n"); + fprintf(cpp, " return false;\n"); + fprintf(cpp, " std::string accumulator;\n"); + fprintf(cpp, " size_t length = strlen(file_path);\n"); + fprintf(cpp, " for(size_t i=0; i + ///This generator generate the File Manager class files. + /// + class ManagerGenerator : public BaseGenerator + { + public: + ManagerGenerator(); + virtual ~ManagerGenerator(); + virtual const char * getName() const; + virtual bool createCppHeaderFile(const char* header_file_path); + virtual bool createCppSourceFile(const char * cpp_file_path); + virtual bool printFileContent(); + }; + +}; //bin2cpp + +#endif //ARRAYGENERATOR_H diff --git a/src/bin2cpp/SegmentGenerator.cpp b/src/bin2cpp/SegmentGenerator.cpp index c82d869..8099bbd 100755 --- a/src/bin2cpp/SegmentGenerator.cpp +++ b/src/bin2cpp/SegmentGenerator.cpp @@ -50,12 +50,12 @@ namespace bin2cpp bool SegmentGenerator::createCppSourceFile(const char * cpp_file_path) { //check if input file exists - FILE * input = fopen(getInputFilePath(), "rb"); + FILE * input = fopen(mContext.inputFilePath.c_str(), "rb"); if (!input) return false; //Uppercase function identifier - std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mFunctionIdentifier); + std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(getContext().functionIdentifier); //Build header and cpp file path std::string headerPath = getHeaderFilePath(cpp_file_path); @@ -71,7 +71,7 @@ namespace bin2cpp //determine file properties uint32_t fileSize = ra::filesystem::GetFileSize(input); - std::string filename = ra::filesystem::GetFilename(getInputFilePath()); + std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); //long lastSegmentSize = fileSize%chunk_size; //size_t numSegments = fileSize/chunk_size + (lastSegmentSize == 0 ? 0 : 1); @@ -82,20 +82,20 @@ namespace bin2cpp std::string getterFunctionName = getGetterFunctionName(); //Build FileManager class template - std::string manager = getManagerHeaderFilename(); + std::string manager = mContext.managerHeaderFilename; //write cpp file heading fprintf(cpp, "%s", getHeaderTemplate().c_str()); fprintf(cpp, "#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)\n"); fprintf(cpp, "#define _CRT_SECURE_NO_WARNINGS\n"); fprintf(cpp, "#endif\n"); - fprintf(cpp, "#include \"%s\"\n", getHeaderFilename() ); + fprintf(cpp, "#include \"%s\"\n", mContext.headerFilename.c_str() ); fprintf(cpp, "#include //for std::string\n"); fprintf(cpp, "#include \n"); fprintf(cpp, "#include //for ofstream\n"); - fprintf(cpp, "namespace %s\n", mNamespace.c_str()); + fprintf(cpp, "namespace %s\n", getContext().codeNamespace.c_str()); fprintf(cpp, "{\n"); - fprintf(cpp, " class %s : public virtual %s::%s\n", className.c_str(), mNamespace.c_str(), mBaseClass.c_str()); + fprintf(cpp, " class %s : public virtual %s::%s\n", className.c_str(), getContext().codeNamespace.c_str(), getContext().baseClass.c_str()); fprintf(cpp, " {\n"); fprintf(cpp, " public:\n"); fprintf(cpp, " %s() { build(); }\n", className.c_str()); @@ -110,11 +110,11 @@ namespace bin2cpp fprintf(cpp, " mBuffer.reserve(getSize()); //allocate all required memory at once to prevent reallocations\n"); //create buffer for each chunks from input buffer - unsigned char * buffer = new unsigned char[mChunkSize]; + unsigned char * buffer = new unsigned char[getContext().chunkSize]; while(!feof(input)) { //read a chunk of the file - size_t readSize = fread(buffer, 1, mChunkSize, input); + size_t readSize = fread(buffer, 1, getContext().chunkSize, input); //bool isLastChunk = !(readSize == chunk_size); @@ -123,12 +123,12 @@ namespace bin2cpp //convert to cpp string std::string cppEncoder; - switch(mCppEncoder) + switch(getContext().cppEncoder) { - case IGenerator::CPP_ENCODER_HEX: + case CPP_ENCODER_HEX: cppEncoder = ra::code::cpp::ToHexString(buffer, readSize); break; - case IGenerator::CPP_ENCODER_OCT: + case CPP_ENCODER_OCT: default: cppEncoder = ra::code::cpp::ToOctString(buffer, readSize, false); break; @@ -146,13 +146,13 @@ namespace bin2cpp fprintf(cpp, " private:\n"); fprintf(cpp, " std::string mBuffer;\n"); fprintf(cpp, " };\n"); - fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", mBaseClass.c_str(), getterFunctionName.c_str(), className.c_str()); - if (isRegisterFileEnabled()) + fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", getContext().baseClass.c_str(), getterFunctionName.c_str(), className.c_str()); + if (mContext.registerFiles) { std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); fprintf(cpp, "%s", fileManagerTemplate.c_str()); } - fprintf(cpp, "}; //%s\n", mNamespace.c_str()); + fprintf(cpp, "}; //%s\n", getContext().codeNamespace.c_str()); fclose(input); fclose(cpp); diff --git a/src/bin2cpp/StringGenerator.cpp b/src/bin2cpp/StringGenerator.cpp index fdf6601..77aaa0a 100755 --- a/src/bin2cpp/StringGenerator.cpp +++ b/src/bin2cpp/StringGenerator.cpp @@ -50,12 +50,12 @@ namespace bin2cpp bool StringGenerator::createCppSourceFile(const char * cpp_file_path) { //check if input file exists - FILE * input = fopen(getInputFilePath(), "rb"); + FILE * input = fopen(mContext.inputFilePath.c_str(), "rb"); if (!input) return false; //Uppercase function identifier - std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mFunctionIdentifier); + std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(getContext().functionIdentifier); //Build header and cpp file path std::string headerPath = getHeaderFilePath(cpp_file_path); @@ -71,7 +71,7 @@ namespace bin2cpp //determine file properties uint32_t fileSize = ra::filesystem::GetFileSize(input); - std::string filename = ra::filesystem::GetFilename(getInputFilePath()); + std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); //Build class name std::string className = getClassName(); @@ -81,12 +81,12 @@ namespace bin2cpp //write cpp file heading fprintf(cpp, "%s", getHeaderTemplate().c_str()); - fprintf(cpp, "#include \"%s\"\n", getHeaderFilename() ); + fprintf(cpp, "#include \"%s\"\n", mContext.headerFilename.c_str() ); fprintf(cpp, "#include \n"); fprintf(cpp, "#include //for ofstream\n"); - fprintf(cpp, "namespace %s\n", mNamespace.c_str()); + fprintf(cpp, "namespace %s\n", getContext().codeNamespace.c_str()); fprintf(cpp, "{\n"); - fprintf(cpp, " class %s : public virtual %s::%s\n", className.c_str(), mNamespace.c_str(), mBaseClass.c_str()); + fprintf(cpp, " class %s : public virtual %s::%s\n", className.c_str(), getContext().codeNamespace.c_str(), getContext().baseClass.c_str()); fprintf(cpp, " {\n"); fprintf(cpp, " public:\n"); fprintf(cpp, " %s() {}\n", className.c_str()); @@ -100,13 +100,13 @@ namespace bin2cpp //create buffer for each chunks from input buffer int numLinePrinted = 0; - unsigned char * buffer = new unsigned char[mChunkSize]; + unsigned char * buffer = new unsigned char[getContext().chunkSize]; while(!feof(input)) { //read a chunk of the file - size_t readSize = fread(buffer, 1, mChunkSize, input); + size_t readSize = fread(buffer, 1, getContext().chunkSize, input); - bool isLastChunk = !(readSize == mChunkSize); + bool isLastChunk = !(readSize == getContext().chunkSize); if (readSize > 0) { @@ -118,12 +118,12 @@ namespace bin2cpp //convert to cpp string std::string cppEncoder; - switch(mCppEncoder) + switch(getContext().cppEncoder) { - case IGenerator::CPP_ENCODER_HEX: + case CPP_ENCODER_HEX: cppEncoder = ra::code::cpp::ToHexString(buffer, readSize); break; - case IGenerator::CPP_ENCODER_OCT: + case CPP_ENCODER_OCT: default: cppEncoder = ra::code::cpp::ToOctString(buffer, readSize, false); break; @@ -148,13 +148,13 @@ namespace bin2cpp fprintf(cpp, " }\n"); fprintf(cpp, "%s", getSaveMethodTemplate().c_str()); fprintf(cpp, " };\n"); - fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", mBaseClass.c_str(), getterFunctionName.c_str(), className.c_str()); - if (isRegisterFileEnabled()) + fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", getContext().baseClass.c_str(), getterFunctionName.c_str(), className.c_str()); + if (mContext.registerFiles) { std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); fprintf(cpp, "%s", fileManagerTemplate.c_str()); } - fprintf(cpp, "}; //%s\n", mNamespace.c_str()); + fprintf(cpp, "}; //%s\n", getContext().codeNamespace.c_str()); fclose(input); fclose(cpp); diff --git a/src/bin2cpp/Win32ResourceGenerator.cpp b/src/bin2cpp/Win32ResourceGenerator.cpp index a22c61f..5db6091 100755 --- a/src/bin2cpp/Win32ResourceGenerator.cpp +++ b/src/bin2cpp/Win32ResourceGenerator.cpp @@ -58,12 +58,12 @@ namespace bin2cpp return false; //check if input file exists - FILE * input = fopen(getInputFilePath(), "rb"); + FILE * input = fopen(mContext.inputFilePath.c_str(), "rb"); if (!input) return false; //Uppercase function identifier - std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mFunctionIdentifier); + std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(getContext().functionIdentifier); //Build header and cpp file path std::string headerPath = getHeaderFilePath(cpp_file_path); @@ -79,7 +79,7 @@ namespace bin2cpp //determine file properties //uint32_t fileSize = ra::filesystem::GetFileSize(input); - std::string filename = ra::filesystem::GetFilename(getInputFilePath()); + std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); //Build class name std::string className = getClassName(); @@ -89,7 +89,7 @@ namespace bin2cpp //write cpp file heading fprintf(cpp, "%s", getHeaderTemplate().c_str()); - fprintf(cpp, "#include \"%s\"\n", getHeaderFilename() ); + fprintf(cpp, "#include \"%s\"\n", mContext.headerFilename.c_str() ); fprintf(cpp, "#include \n"); fprintf(cpp, "#include \n"); fprintf(cpp, "#include //for ofstream\n"); @@ -103,9 +103,9 @@ namespace bin2cpp fprintf(cpp, "#pragma comment( lib, \"psapi.lib\" )\n"); fprintf(cpp, "\n"); - fprintf(cpp, "namespace %s\n", mNamespace.c_str()); + fprintf(cpp, "namespace %s\n", getContext().codeNamespace.c_str()); fprintf(cpp, "{\n"); - fprintf(cpp, " class %s : public virtual %s::%s\n", className.c_str(), mNamespace.c_str(), mBaseClass.c_str()); + fprintf(cpp, " class %s : public virtual %s::%s\n", className.c_str(), getContext().codeNamespace.c_str(), getContext().baseClass.c_str()); fprintf(cpp, " {\n"); fprintf(cpp, " public:\n"); fprintf(cpp, " %s() :\n", className.c_str()); @@ -134,7 +134,7 @@ namespace bin2cpp fprintf(cpp, " if ( EnumProcessModules( hProcess, &hModule, sizeof(hModule), &cbNeeded) )\n"); fprintf(cpp, " {\n"); fprintf(cpp, " //Retrieve the resource\n"); - fprintf(cpp, " hResourceInfoBlock = FindResource(hModule, \"%s\", \"CUSTOM\");\n", getRandomIdentifier(getInputFilePath()).c_str()); + fprintf(cpp, " hResourceInfoBlock = FindResource(hModule, \"%s\", \"CUSTOM\");\n", getRandomIdentifier(mContext.inputFilePath.c_str()).c_str()); fprintf(cpp, " if (hResourceInfoBlock)\n"); fprintf(cpp, " {\n"); fprintf(cpp, " hResHandle = LoadResource(hModule, hResourceInfoBlock);\n"); @@ -173,13 +173,13 @@ namespace bin2cpp fprintf(cpp, " DWORD mBufferSize;\n"); fprintf(cpp, " const char * mBuffer;\n"); fprintf(cpp, " };\n"); - fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", mBaseClass.c_str(), getterFunctionName.c_str(), className.c_str()); - if (isRegisterFileEnabled()) + fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", getContext().baseClass.c_str(), getterFunctionName.c_str(), className.c_str()); + if (mContext.registerFiles) { std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); fprintf(cpp, "%s", fileManagerTemplate.c_str()); } - fprintf(cpp, "}; //%s\n", mNamespace.c_str()); + fprintf(cpp, "}; //%s\n", getContext().codeNamespace.c_str()); fclose(input); fclose(cpp); @@ -207,12 +207,12 @@ namespace bin2cpp return false; } - std::string filename = ra::filesystem::GetFilename(getInputFilePath()); + std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); //write res file heading fprintf(res, "%s", getHeaderTemplate().c_str()); fprintf(res, "#include \n"); - fprintf(res, "%s CUSTOM \"%s\"\n", getRandomIdentifier(getInputFilePath()).c_str(), filename.c_str()); + fprintf(res, "%s CUSTOM \"%s\"\n", getRandomIdentifier(mContext.inputFilePath.c_str()).c_str(), filename.c_str()); fclose(res); diff --git a/src/bin2cpp/bin2cpp.samples.txt b/src/bin2cpp/bin2cpp.samples.txt index d8ff769..e912fdc 100644 --- a/src/bin2cpp/bin2cpp.samples.txt +++ b/src/bin2cpp/bin2cpp.samples.txt @@ -26,3 +26,6 @@ --file=..\..\test\bin2cpp_unittest\generated_files\testText1000\testText1000.bin --output=. --override --noheader --dir=..\..\test\bin2cpp_unittest\generated_files\testIssue56a\input_files --output=..\..\test\bin2cpp_unittest\generated_files\testIssue56a\compiled_sources --chunksize=200 --managerfile=FileManager56a.h --registerfile --namespace=issue56a --override + + +--plainoutput --chunksize=9999 --file=..\..\test\bin2cpp_unittest\generated_files\testSequential1000\testSequential1000.bin diff --git a/src/bin2cpp/enums.h b/src/bin2cpp/enums.h new file mode 100644 index 0000000..a5398aa --- /dev/null +++ b/src/bin2cpp/enums.h @@ -0,0 +1,46 @@ +/********************************************************************************** + * MIT License + * + * Copyright (c) 2018 Antoine Beauchamp + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *********************************************************************************/ + +#ifndef ENUMS_H +#define ENUMS_H + +#include +#include "Context.h" + +namespace bin2cpp +{ + + /// + ///Defines the different type of cpp encoding. + ///See setCppEncoder() and getCppEncoder() functions. + /// + enum CppEncoderEnum + { + CPP_ENCODER_OCT, + CPP_ENCODER_HEX, + }; + +}; //bin2cpp + +#endif //IGENERATOR_H diff --git a/src/bin2cpp/main.cpp b/src/bin2cpp/main.cpp index 1c751f3..53e53c4 100755 --- a/src/bin2cpp/main.cpp +++ b/src/bin2cpp/main.cpp @@ -29,6 +29,8 @@ #include "StringGenerator.h" #include "ArrayGenerator.h" #include "Win32ResourceGenerator.h" +#include "ManagerGenerator.h" +#include "Context.h" #include #include @@ -69,7 +71,7 @@ enum FILE_UPDATE_MODE static const size_t DEFAULT_CHUNK_SIZE = 200; static const char * DEFAULT_NAMESPACE = "bin2cpp"; static const char * DEFAULT_BASECLASSNAME = "File"; -static const IGenerator::CppEncoderEnum DEFAULT_ENCODING = IGenerator::CPP_ENCODER_OCT; +static const CppEncoderEnum DEFAULT_ENCODING = CPP_ENCODER_OCT; static Dictionary identifiers_dictionary; // unique values for identifiers static Dictionary output_files_dictionary; // unique values for output file names @@ -129,37 +131,17 @@ struct ARGUMENTS bool noheader; bool quiet; bool version; - bool hasFile; // true if 'inputFilePath' is set. - bool hasDir; // true if 'inputDirPath' is set. - bool hasReportedFilePath; // true if 'reportedFilePath' is set. - bool hasManagerFile; // true if 'managerHeaderFilename' is set. - bool keepDirectoryStructure; // true if the output files must have the same directory structure as the input files. Valid only when --dir is used. - std::string inputFilePath; // path of the input binary file - std::string inputDirPath; - std::string outputDirPath; - std::string headerFilename; - std::string functionIdentifier; - std::string reportedFilePath; // path reported in the public api when calling getFilePath(); - size_t chunkSize; - bool plainOutput; - bool overrideExisting; - std::string codeNamespace; - std::string baseClass; - std::string managerHeaderFilename; - bool registerfile; - IGenerator::CppEncoderEnum encoding; std::string generatorName; }; //pre-declarations -bool generateFile(const ARGUMENTS & args, const std::string & output_file_path, bin2cpp::IGenerator * generator); -bool generateManagerFile(const ARGUMENTS & args, const std::string & output_file_path, bin2cpp::IGenerator * generator); -APP_ERROR_CODES processInputFile(const ARGUMENTS & args, bin2cpp::IGenerator * generator); -APP_ERROR_CODES processInputDirectory(const ARGUMENTS & args, bin2cpp::IGenerator * generator); -APP_ERROR_CODES processManagerFiles(const ARGUMENTS & args, bin2cpp::IGenerator * generator); -APP_ERROR_CODES processPlainOutput(const ARGUMENTS & args, bin2cpp::IGenerator * generator); -std::string getDefaultFunctionIdentifier(const ARGUMENTS & args, Dictionary & identifiers_dictionary); -std::string getDefaultHeaderFile(const ARGUMENTS & args); +bool generateFile(const Context & c, const std::string & output_file_path, bin2cpp::IGenerator * generator); +APP_ERROR_CODES processInputFile(const Context & c, bin2cpp::IGenerator * generator); +APP_ERROR_CODES processInputDirectory(const Context & c, bin2cpp::IGenerator * generator); +APP_ERROR_CODES processManagerFiles(const Context & c); +APP_ERROR_CODES processPlainOutput(const Context & c, bin2cpp::IGenerator * generator); +std::string getDefaultFunctionIdentifier(const Context & c, Dictionary & identifiers_dictionary); +std::string getDefaultHeaderFile(const Context & c); void printHeader() { @@ -222,15 +204,8 @@ int main(int argc, char* argv[]) args.noheader = false; args.quiet = false; args.version = false; - args.hasFile = false; - args.hasDir = false; - args.hasReportedFilePath = false; - args.hasManagerFile = false; - args.keepDirectoryStructure = false; - args.chunkSize = 0; - args.plainOutput = false; - args.overrideExisting = false; - args.registerfile = false; + + Context c; std::string dummy; @@ -250,8 +225,8 @@ int main(int argc, char* argv[]) args.quiet = ra::cli::ParseArgument("quiet", dummy, argc, argv); //force quiet and noheader if plain output - args.plainOutput = ra::cli::ParseArgument("plainoutput", dummy, argc, argv); - if (args.plainOutput) + c.plainOutput = ra::cli::ParseArgument("plainoutput", dummy, argc, argv); + if ( c.plainOutput ) { args.quiet = true; args.noheader = true; @@ -276,12 +251,12 @@ int main(int argc, char* argv[]) printHeader(); //mandatory arguments - args.hasFile = ra::cli::ParseArgument("file", args.inputFilePath, argc, argv); - args.hasDir = ra::cli::ParseArgument("dir", args.inputDirPath, argc, argv); - args.hasManagerFile = ra::cli::ParseArgument("managerfile", args.managerHeaderFilename, argc, argv); + c.hasInputFile = ra::cli::ParseArgument("file", c.inputFilePath, argc, argv); + c.hasInputDir = ra::cli::ParseArgument("dir", c.inputDirPath, argc, argv); + c.hasManagerFile = ra::cli::ParseArgument("managerfile", c.managerHeaderFilename, argc, argv); //if no mandatory args is specified - if (!args.hasFile && !args.hasDir && !args.hasManagerFile && !args.plainOutput) + if (!c.hasInputFile && !c.hasInputDir && !c.hasManagerFile && !c.plainOutput) { //file, dir, managerfile or plainoutput must be specified APP_ERROR_CODES error = APP_ERROR_MISSINGARGUMENTS; @@ -289,7 +264,7 @@ int main(int argc, char* argv[]) printUsage(); return error; } - else if (args.hasFile && args.hasDir) + else if (c.hasInputFile && c.hasInputDir) { //file OR dir must be specified, not both APP_ERROR_CODES error = APP_ERROR_TOOMANYARGUMENTS; @@ -299,9 +274,10 @@ int main(int argc, char* argv[]) } //if output args is mandatory - if (args.hasDir || (args.hasFile && !args.plainOutput) || args.hasManagerFile) + if (c.hasInputDir || (c.hasInputFile && !c.plainOutput) || c.hasManagerFile) { - if (!ra::cli::ParseArgument("output", args.outputDirPath, argc, argv)) + c.hasOutputDir = ra::cli::ParseArgument("output", c.outputDirPath, argc, argv); + if (!c.hasOutputDir ) { APP_ERROR_CODES error = APP_ERROR_MISSINGARGUMENTS; ra::logging::Log(ra::logging::LOG_ERROR, "%s (output)", getErrorCodeDescription(error)); @@ -311,9 +287,9 @@ int main(int argc, char* argv[]) } // if headerfile should not be specified - if (args.hasDir) + if (c.hasInputDir) { - if (ra::cli::ParseArgument("headerfile", args.headerFilename, argc, argv)) + if (ra::cli::ParseArgument("headerfile", c.headerFilename, argc, argv)) { //headerfile not supported with dir argument APP_ERROR_CODES error = APP_ERROR_TOOMANYARGUMENTS; @@ -324,9 +300,9 @@ int main(int argc, char* argv[]) } // if identifier should not be specified - if (args.hasDir) + if (c.hasInputDir) { - if (ra::cli::ParseArgument("identifier", args.functionIdentifier, argc, argv)) + if (ra::cli::ParseArgument("identifier", c.functionIdentifier, argc, argv)) { //identifier not supported with dir argument APP_ERROR_CODES error = APP_ERROR_TOOMANYARGUMENTS; @@ -338,52 +314,52 @@ int main(int argc, char* argv[]) //optional arguments - if (args.hasFile) + if (c.hasInputFile) { //identifier - if (!ra::cli::ParseArgument("identifier", args.functionIdentifier, argc, argv)) + if (!ra::cli::ParseArgument("identifier", c.functionIdentifier, argc, argv)) { //identifier is not manually specified. - args.functionIdentifier = getDefaultFunctionIdentifier(args, identifiers_dictionary); + c.functionIdentifier = getDefaultFunctionIdentifier(c, identifiers_dictionary); } //headerfile - if (!ra::cli::ParseArgument("headerfile", args.headerFilename, argc, argv)) + if (!ra::cli::ParseArgument("headerfile", c.headerFilename, argc, argv)) { //use the file name without extension as 'headerfile'. - args.headerFilename = getDefaultHeaderFile(args); + c.headerFilename = getDefaultHeaderFile(c); } } size_t tmpChunkSize = 0; - args.chunkSize = DEFAULT_CHUNK_SIZE; + c.chunkSize = DEFAULT_CHUNK_SIZE; if (ra::cli::ParseArgument("chunksize", tmpChunkSize, argc, argv)) { - args.chunkSize = tmpChunkSize; + c.chunkSize = tmpChunkSize; } - args.overrideExisting = ra::cli::ParseArgument("override", dummy, argc, argv); + c.overrideExistingFiles = ra::cli::ParseArgument("override", dummy, argc, argv); - if (!ra::cli::ParseArgument("namespace", args.codeNamespace, argc, argv)) + if (!ra::cli::ParseArgument("namespace", c.codeNamespace, argc, argv)) { - args.codeNamespace = DEFAULT_NAMESPACE; + c.codeNamespace = DEFAULT_NAMESPACE; } - if (!ra::cli::ParseArgument("baseclass", args.baseClass, argc, argv)) + if (!ra::cli::ParseArgument("baseclass", c.baseClass, argc, argv)) { - args.baseClass = DEFAULT_BASECLASSNAME; + c.baseClass = DEFAULT_BASECLASSNAME; } - args.registerfile = ra::cli::ParseArgument("registerfile", dummy, argc, argv); + c.registerFiles = ra::cli::ParseArgument("registerfile", dummy, argc, argv); //force registerfile if managerfile is specified - if (args.hasManagerFile) + if (c.hasManagerFile) { - args.registerfile = true; + c.registerFiles = true; } - args.hasReportedFilePath = ra::cli::ParseArgument("reportedfilepath", args.reportedFilePath, argc, argv); - if (args.hasReportedFilePath && args.hasDir) + c.hasReportedFilePath = ra::cli::ParseArgument("reportedfilepath", c.reportedFilePath, argc, argv); + if (c.hasReportedFilePath && c.hasInputDir) { APP_ERROR_CODES error = APP_ERROR_TOOMANYARGUMENTS; ra::logging::Log(ra::logging::LOG_ERROR, "%s (reportedfilepath)", getErrorCodeDescription(error)); @@ -391,15 +367,15 @@ int main(int argc, char* argv[]) return error; } - args.keepDirectoryStructure = ra::cli::ParseArgument("keepdirs", dummy, argc, argv); + c.keepDirectoryStructure = ra::cli::ParseArgument("keepdirs", dummy, argc, argv); std::string encodingStr; if (ra::cli::ParseArgument("encoding", encodingStr, argc, argv)) { if (ra::strings::Uppercase(encodingStr) == "OCT") - args.encoding = IGenerator::CPP_ENCODER_OCT; + c.cppEncoder = CPP_ENCODER_OCT; else if (ra::strings::Uppercase(encodingStr) == "HEX") - args.encoding = IGenerator::CPP_ENCODER_HEX; + c.cppEncoder = CPP_ENCODER_HEX; else { APP_ERROR_CODES error = APP_ERROR_MISSINGARGUMENTS; @@ -410,7 +386,7 @@ int main(int argc, char* argv[]) } else { - args.encoding = DEFAULT_ENCODING; + c.cppEncoder = DEFAULT_ENCODING; } //select generator @@ -450,7 +426,7 @@ int main(int argc, char* argv[]) } //win32 generator does not support plain output - if (args.generatorName == "win32" && args.plainOutput) + if (args.generatorName == "win32" && c.plainOutput) { APP_ERROR_CODES error = AAP_ERROR_NOTSUPPORTED; ra::logging::Log(ra::logging::LOG_ERROR, "%s.", getErrorCodeDescription(error)); @@ -464,27 +440,27 @@ int main(int argc, char* argv[]) } //process file, directory or plain format - if (args.plainOutput) + if (c.plainOutput) { - APP_ERROR_CODES error = processPlainOutput(args, generator); + APP_ERROR_CODES error = processPlainOutput(c, generator); if (error != APP_ERROR_SUCCESS) { ra::logging::Log(ra::logging::LOG_ERROR, "%s.", getErrorCodeDescription(error)); return error; } } - else if (args.hasFile) + else if (c.hasInputFile) { - APP_ERROR_CODES error = processInputFile(args, generator); + APP_ERROR_CODES error = processInputFile(c, generator); if (error != APP_ERROR_SUCCESS) { ra::logging::Log(ra::logging::LOG_ERROR, "%s.", getErrorCodeDescription(error)); return error; } } - else if (args.hasDir) + else if (c.hasInputDir) { - APP_ERROR_CODES error = processInputDirectory(args, generator); + APP_ERROR_CODES error = processInputDirectory(c, generator); if (error != APP_ERROR_SUCCESS) { ra::logging::Log(ra::logging::LOG_ERROR, "%s.", getErrorCodeDescription(error)); @@ -493,9 +469,9 @@ int main(int argc, char* argv[]) } //should we also generate the FileManager class? - if (args.hasManagerFile) + if (c.hasManagerFile) { - APP_ERROR_CODES error = processManagerFiles(args, generator); + APP_ERROR_CODES error = processManagerFiles(c); if (error != APP_ERROR_SUCCESS) { ra::logging::Log(ra::logging::LOG_ERROR, "%s.", getErrorCodeDescription(error)); @@ -506,77 +482,71 @@ int main(int argc, char* argv[]) return APP_ERROR_SUCCESS; } -std::string getDefaultFunctionIdentifier(const ARGUMENTS & args, Dictionary & identifiers_dictionary) +std::string getDefaultFunctionIdentifier(const Context & c, Dictionary & identifiers_dictionary) { std::string output; //use the file name without extension as 'identifier'. - output = getUniqueFunctionIdentifierFromPath(args.inputFilePath.c_str(), identifiers_dictionary); + output = getUniqueFunctionIdentifierFromPath(c.inputFilePath.c_str(), identifiers_dictionary); output = ra::strings::CapitalizeFirstCharacter(output); return output; } -std::string getDefaultHeaderFile(const ARGUMENTS & args) +std::string getDefaultHeaderFile(const Context & c) { std::string output; //use the file name without extension as 'headerfile'. - output = ra::filesystem::GetFilenameWithoutExtension(args.inputFilePath.c_str()); + output = ra::filesystem::GetFilenameWithoutExtension(c.inputFilePath.c_str()); output += ".h"; return output; } -APP_ERROR_CODES processInputFile(const ARGUMENTS & args, bin2cpp::IGenerator * generator) +APP_ERROR_CODES processInputFile(const Context & c, bin2cpp::IGenerator * generator) { // printing info std::string info; - info << "Embedding \"" << args.inputFilePath << "\""; - if (args.chunkSize != DEFAULT_CHUNK_SIZE) + info << "Embedding \"" << c.inputFilePath << "\""; + if (c.chunkSize != DEFAULT_CHUNK_SIZE) { info << " using chunks of "; - info << ra::strings::ToString(args.chunkSize); + info << ra::strings::ToString(c.chunkSize); info << " bytes"; } - if (args.overrideExisting) + if (c.overrideExistingFiles) info << " overriding existing files"; info << "..."; ra::logging::Log(ra::logging::LOG_INFO, info.c_str()); //check if input file exists - if (!ra::filesystem::FileExists(args.inputFilePath.c_str())) + if (!ra::filesystem::FileExists(c.inputFilePath.c_str())) return APP_ERROR_INPUTFILENOTFOUND; - ARGUMENTS argsCopy = args; - //prepare output files path - std::string cppFilename = argsCopy.headerFilename; + std::string cppFilename = c.headerFilename; ra::strings::Replace(cppFilename, ".hpp", ".cpp"); ra::strings::Replace(cppFilename, ".h", ".cpp"); + //create a copy of the context. + //we may have already generated files from a previous call to processInputFile(). + //make sure the file paths are unique. + Context cCopy = c; + //build unique output relative file paths - argsCopy.headerFilename = bin2cpp::getUniqueFilePath(argsCopy.headerFilename, output_files_dictionary); + cCopy.headerFilename = bin2cpp::getUniqueFilePath(cCopy.headerFilename, output_files_dictionary); cppFilename = bin2cpp::getUniqueFilePath(cppFilename, output_files_dictionary); //build full absolute paths - std::string outputHeaderPath = argsCopy.outputDirPath + ra::filesystem::GetPathSeparatorStr() + argsCopy.headerFilename; - std::string outputCppPath = argsCopy.outputDirPath + ra::filesystem::GetPathSeparatorStr() + cppFilename; + std::string outputHeaderPath = cCopy.outputDirPath + ra::filesystem::GetPathSeparatorStr() + cCopy.headerFilename; + std::string outputCppPath = cCopy.outputDirPath + ra::filesystem::GetPathSeparatorStr() + cppFilename; //configure the generator - generator->setInputFilePath(argsCopy.inputFilePath.c_str()); - generator->setHeaderFilename(argsCopy.headerFilename.c_str()); - generator->setFunctionIdentifier(argsCopy.functionIdentifier.c_str()); - generator->setReportedFilePath(argsCopy.reportedFilePath.c_str()); - generator->setChunkSize(argsCopy.chunkSize); - generator->setNamespace(argsCopy.codeNamespace.c_str()); - generator->setBaseClass(argsCopy.baseClass.c_str()); - generator->setCppEncoder(argsCopy.encoding); - generator->setManagerHeaderFilename(argsCopy.managerHeaderFilename.c_str()); - generator->setRegisterFileEnabled(argsCopy.registerfile); + generator->setContext(cCopy); //build the output directory structure if required - if (argsCopy.keepDirectoryStructure) + if (cCopy.keepDirectoryStructure) { std::string parent_directory = ra::filesystem::GetParentPath(outputHeaderPath); if (!parent_directory.empty() && !ra::filesystem::DirectoryExists(parent_directory.c_str())) @@ -592,11 +562,11 @@ APP_ERROR_CODES processInputFile(const ARGUMENTS & args, bin2cpp::IGenerator * g } //process files - bool headerResult = generateFile(args, outputHeaderPath, generator); + bool headerResult = generateFile(c, outputHeaderPath, generator); if (!headerResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; - bool cppResult = generateFile(args, outputCppPath, generator); + bool cppResult = generateFile(c, outputCppPath, generator); if (!cppResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; @@ -604,23 +574,23 @@ APP_ERROR_CODES processInputFile(const ARGUMENTS & args, bin2cpp::IGenerator * g return APP_ERROR_SUCCESS; } -APP_ERROR_CODES processInputDirectory(const ARGUMENTS & args, bin2cpp::IGenerator * generator) +APP_ERROR_CODES processInputDirectory(const Context& c, bin2cpp::IGenerator * generator) { //check if input dir exists - if (!ra::filesystem::DirectoryExists(args.inputDirPath.c_str())) + if (!ra::filesystem::DirectoryExists(c.inputDirPath.c_str())) { APP_ERROR_CODES error = APP_ERROR_INPUTDIRNOTFOUND; - ra::logging::Log(ra::logging::LOG_ERROR, "%s (%s)", getErrorCodeDescription(error), args.inputDirPath.c_str()); + ra::logging::Log(ra::logging::LOG_ERROR, "%s (%s)", getErrorCodeDescription(error), c.inputDirPath.c_str()); return error; } //search all files in the directory ra::strings::StringVector files; - bool found = ra::filesystem::FindFiles(files, args.inputDirPath.c_str()); + bool found = ra::filesystem::FindFiles(files, c.inputDirPath.c_str()); if (!found) { APP_ERROR_CODES error = APP_ERROR_INPUTDIRNOTFOUND; - ra::logging::Log(ra::logging::LOG_ERROR, "%s (%s)", getErrorCodeDescription(error), args.inputDirPath.c_str()); + ra::logging::Log(ra::logging::LOG_ERROR, "%s (%s)", getErrorCodeDescription(error), c.inputDirPath.c_str()); return error; } @@ -644,29 +614,29 @@ APP_ERROR_CODES processInputDirectory(const ARGUMENTS & args, bin2cpp::IGenerato const std::string & file = files[i]; //build a 'headerfile' and 'identifier' argument for this file... - ARGUMENTS argsCopy = args; + Context cCopy = c; //replace 'dir' input by current file input - argsCopy.hasDir = false; - argsCopy.hasFile = true; - argsCopy.inputFilePath = file; + cCopy.hasInputDir = false; + cCopy.hasInputFile = true; + cCopy.inputFilePath = file; //use the file name without extension as 'headerfile'. - argsCopy.headerFilename = getDefaultHeaderFile(argsCopy); + cCopy.headerFilename = getDefaultHeaderFile(cCopy); //use the file name without extension as 'identifier'. - argsCopy.functionIdentifier = getDefaultFunctionIdentifier(argsCopy, identifiers_dictionary); + cCopy.functionIdentifier = getDefaultFunctionIdentifier(cCopy, identifiers_dictionary); //build a relative file path std::string relative_file_path = file; - relative_file_path.erase(0, argsCopy.inputDirPath.size() + 1 ); // convert absolute path to relative path. +1 to remove first \ character + relative_file_path.erase(0, cCopy.inputDirPath.size() + 1 ); // convert absolute path to relative path. +1 to remove first \ character ra::filesystem::NormalizePath(relative_file_path); //automatically build a reported path with --dir mode. - argsCopy.hasReportedFilePath = true; - argsCopy.reportedFilePath = relative_file_path; + cCopy.hasReportedFilePath = true; + cCopy.reportedFilePath = relative_file_path; - if (args.keepDirectoryStructure) + if (c.keepDirectoryStructure) { // To keep the directory structure, we need to // make headerFilename a relative path @@ -681,11 +651,11 @@ APP_ERROR_CODES processInputDirectory(const ARGUMENTS & args, bin2cpp::IGenerato relative_header_file_path += "h"; } - argsCopy.headerFilename = relative_header_file_path; + cCopy.headerFilename = relative_header_file_path; } //process this file... - APP_ERROR_CODES error = processInputFile(argsCopy, generator); + APP_ERROR_CODES error = processInputFile(cCopy, generator); if (error != APP_ERROR_SUCCESS) return error; @@ -717,9 +687,9 @@ FILE_UPDATE_MODE getFileUpdateMode(const std::string & input_file_path, const st return UPDATING; } -bool generateFile(const ARGUMENTS & args, const std::string & output_file_path, bin2cpp::IGenerator * generator) +bool generateFile(const Context & c, const std::string & output_file_path, bin2cpp::IGenerator * generator) { - FILE_UPDATE_MODE mode = getFileUpdateMode(args.inputFilePath, output_file_path, args.overrideExisting); + FILE_UPDATE_MODE mode = getFileUpdateMode(c.inputFilePath, output_file_path, c.overrideExistingFiles); //writing message ra::logging::Log(ra::logging::LOG_INFO, "%s file \"%s\"...", getUpdateModeText(mode), output_file_path.c_str()); @@ -748,60 +718,34 @@ bool generateFile(const ARGUMENTS & args, const std::string & output_file_path, return result; } -bool generateManagerFile(const ARGUMENTS & args, const std::string & output_file_path, bin2cpp::IGenerator * generator) -{ - std::string processPath = ra::process::GetCurrentProcessPath(); - FILE_UPDATE_MODE mode = getFileUpdateMode(processPath, output_file_path, args.overrideExisting); - - //writing message - ra::logging::Log(ra::logging::LOG_INFO, "%s file \"%s\"...", getUpdateModeText(mode), output_file_path.c_str()); - - if (mode == SKIPPING) - return true; //skipping is success - - //generate file - bool result = false; - if (isCppHeaderFile(output_file_path)) - { - //generate header - result = generator->createManagerHeaderFile(output_file_path.c_str()); - } - else - { - //generate cpp - result = generator->createManagerSourceFile(output_file_path.c_str()); - } - if (!result) - { - //there was an error generating file - ra::logging::Log(ra::logging::LOG_ERROR, "%s failed!", getUpdateModeText(mode)); - } - return result; -} - -APP_ERROR_CODES processManagerFiles(const ARGUMENTS & args, bin2cpp::IGenerator * generator) +APP_ERROR_CODES processManagerFiles(const Context & c) { // printing info std::string info; - info << "Generating \"" << args.managerHeaderFilename << "\""; - if (args.overrideExisting) + info << "Generating \"" << c.managerHeaderFilename << "\""; + if (c.overrideExistingFiles) info << " overriding existing files"; info << "..."; ra::logging::Log(ra::logging::LOG_INFO, info.c_str()); //prepare output files path - std::string cppFilename = args.managerHeaderFilename; + std::string cppFilename = c.managerHeaderFilename; ra::strings::Replace(cppFilename, ".hpp", ".cpp"); ra::strings::Replace(cppFilename, ".h", ".cpp"); - std::string outputHeaderPath = args.outputDirPath + ra::filesystem::GetPathSeparatorStr() + args.managerHeaderFilename; - std::string outputCppPath = args.outputDirPath + ra::filesystem::GetPathSeparatorStr() + cppFilename; + std::string outputHeaderPath = c.outputDirPath + ra::filesystem::GetPathSeparatorStr() + c.managerHeaderFilename; + std::string outputCppPath = c.outputDirPath + ra::filesystem::GetPathSeparatorStr() + cppFilename; + + ManagerGenerator generator; + + //configure the generator + generator.setContext(c); //process files - bool headerResult = generateManagerFile(args, outputHeaderPath, generator); + bool headerResult = generateFile(c, outputHeaderPath, &generator); if (!headerResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; - bool cppResult = generateManagerFile(args, outputCppPath, generator); + bool cppResult = generateFile(c, outputCppPath, &generator); if (!cppResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; @@ -809,18 +753,14 @@ APP_ERROR_CODES processManagerFiles(const ARGUMENTS & args, bin2cpp::IGenerator return APP_ERROR_SUCCESS; } -APP_ERROR_CODES processPlainOutput(const ARGUMENTS & args, bin2cpp::IGenerator * generator) +APP_ERROR_CODES processPlainOutput(const Context & c, bin2cpp::IGenerator * generator) { //check if input file exists - if (!ra::filesystem::FileExists(args.inputFilePath.c_str())) + if (!ra::filesystem::FileExists(c.inputFilePath.c_str())) return APP_ERROR_INPUTFILENOTFOUND; - ARGUMENTS argsCopy = args; - //configure the generator - generator->setInputFilePath(argsCopy.inputFilePath.c_str()); - generator->setChunkSize(argsCopy.chunkSize); - generator->setCppEncoder(argsCopy.encoding); + generator->setContext(c); //process file bool result = generator->printFileContent();