| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2022 - Raw Material Software Limited
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    By using JUCE, you agree to the terms of both the JUCE 7 End-User License
 -    Agreement and JUCE Privacy Policy.
 - 
 -    End User License Agreement: www.juce.com/juce-7-licence
 -    Privacy Policy: www.juce.com/juce-privacy-policy
 - 
 -    Or: You may also use this code under the terms of the GPL v3 (see
 -    www.gnu.org/licenses).
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - #include <sys/stat.h>
 - #include <unistd.h>
 - 
 - #include <algorithm>
 - #include <cstdint>
 - #include <fstream>
 - #include <iomanip>
 - #include <iostream>
 - #include <optional>
 - #include <vector>
 - 
 - //==============================================================================
 - struct FileHelpers
 - {
 -     static std::string getCurrentWorkingDirectory()
 -     {
 -         std::vector<char> buffer (1024);
 - 
 -         while (getcwd (buffer.data(), buffer.size() - 1) == nullptr && errno == ERANGE)
 -             buffer.resize (buffer.size() * 2 / 3);
 - 
 -         return { buffer.data() };
 -     }
 - 
 -     static bool endsWith (const std::string& s, char c)
 -     {
 -         if (s.length() == 0)
 -             return false;
 - 
 -         return *s.rbegin() == c;
 -     }
 - 
 -     static std::string appendedPaths (const std::string& first, const std::string& second)
 -     {
 -         return endsWith (first, '/') ? first + second : first + "/" + second;
 -     }
 - 
 -     static bool exists (const std::string& path)
 -     {
 -         return ! path.empty() && access (path.c_str(), F_OK) == 0;
 -     }
 - 
 -     static bool deleteFile (const std::string& path)
 -     {
 -         if (! exists (path))
 -             return true;
 - 
 -         return remove (path.c_str()) == 0;
 -     }
 - 
 -     static std::string getFilename (const std::string& path)
 -     {
 -         return { std::find_if (path.rbegin(), path.rend(), [] (auto c) { return c == '/'; }).base(),
 -                  path.end() };
 -     }
 - 
 -     static bool isDirectory (const std::string& path)
 -     {
 -        #if defined (__FreeBSD__) || defined (__OpenBSD__)
 -         #define JUCE_STAT stat
 -        #else
 -         #define JUCE_STAT stat64
 -        #endif
 - 
 -         struct JUCE_STAT info;
 - 
 -         return    ! path.empty()
 -                && JUCE_STAT (path.c_str(), &info) == 0
 -                && ((info.st_mode & S_IFDIR) != 0);
 -     }
 - 
 -     static std::string getParentDirectory (const std::string& path)
 -     {
 -         std::string p { path.begin(),
 -                         std::find_if (path.rbegin(),
 -                                       path.rend(),
 -                                       [] (auto c) { return c == '/'; }).base() };
 - 
 -         // Trim the ending slash, but only if not root
 -         if (endsWith (p, '/') && p.length() > 1)
 -             return { p.begin(), p.end() - 1 };
 - 
 -         return p;
 -     }
 - 
 -     static bool createDirectory (const std::string& path)
 -     {
 -         if (isDirectory (path))
 -             return true;
 - 
 -         const auto parentDir = getParentDirectory (path);
 - 
 -         if (path == parentDir)
 -             return false;
 - 
 -         if (createDirectory (parentDir))
 -             return mkdir (path.c_str(), 0777) != -1;
 - 
 -         return false;
 -     }
 - };
 - 
 - //==============================================================================
 - struct StringHelpers
 - {
 -     static bool isQuoteCharacter (char c)
 -     {
 -         return c == '"' || c == '\'';
 -     }
 - 
 -     static std::string unquoted (const std::string& str)
 -     {
 -         if (str.length() == 0 || (! isQuoteCharacter (str[0])))
 -             return str;
 - 
 -         return str.substr (1, str.length() - (isQuoteCharacter (str[str.length() - 1]) ? 1 : 0));
 -     }
 - 
 -     static void ltrim (std::string& s)
 -     {
 -         s.erase (s.begin(), std::find_if (s.begin(), s.end(), [] (int c) { return ! std::isspace (c); }));
 -     }
 - 
 -     static void rtrim (std::string& s)
 -     {
 -         s.erase (std::find_if (s.rbegin(), s.rend(), [] (int c) { return ! std::isspace (c); }).base(), s.end());
 -     }
 - 
 -     static std::string trimmed (const std::string& str)
 -     {
 -         auto result = str;
 -         ltrim (result);
 -         rtrim (result);
 -         return result;
 -     }
 - 
 -     static std::string replaced (const std::string& str, char charToReplace, char replaceWith)
 -     {
 -         auto result = str;
 -         std::replace (result.begin(), result.end(), charToReplace, replaceWith);
 -         return result;
 -     }
 - };
 - 
 - //==============================================================================
 - static bool addFile (const std::string& filePath,
 -                      const std::string& binaryNamespace,
 -                      std::ofstream& headerStream,
 -                      std::ofstream& cppStream,
 -                      bool verbose)
 - {
 -     std::ifstream fileStream (filePath, std::ios::in | std::ios::binary | std::ios::ate);
 - 
 -     if (! fileStream.is_open())
 -     {
 -         std::cerr << "Failed to open input file " << filePath << std::endl;
 -         return false;
 -     }
 - 
 -     std::vector<char> buffer ((size_t) fileStream.tellg());
 -     fileStream.seekg (0);
 -     fileStream.read (buffer.data(), static_cast<std::streamsize> (buffer.size()));
 - 
 -     const auto variableName = StringHelpers::replaced (StringHelpers::replaced (FileHelpers::getFilename (filePath),
 -                                                                                 ' ',
 -                                                                                 '_'),
 -                                                        '.',
 -                                                        '_');
 - 
 -     if (verbose)
 -     {
 -         std::cout << "Adding " << variableName << ": "
 -                   << buffer.size() << " bytes" << std::endl;
 -     }
 - 
 -     headerStream << "    extern const char*  " << variableName << ";" << std::endl
 -                  << "    const int           " << variableName << "Size = "
 -                  << buffer.size() << ";" << std::endl;
 - 
 -     cppStream << "static const unsigned char temp0[] = {";
 - 
 -     auto* data = (const uint8_t*) buffer.data();
 - 
 -     for (size_t i = 0; i < buffer.size() - 1; ++i)
 -     {
 -         cppStream << (int) data[i] << ",";
 - 
 -         if ((i % 40) == 39)
 -             cppStream << std::endl << "  ";
 -     }
 - 
 -     cppStream << (int) data[buffer.size() - 1] << ",0,0};" << std::endl;
 -     cppStream << "const char* " << binaryNamespace << "::" << variableName
 -               << " = (const char*) temp0" << ";" << std::endl << std::endl;
 - 
 -     return true;
 - }
 - 
 - //==============================================================================
 - class Arguments
 - {
 - public:
 -     enum class PositionalArguments
 -     {
 -         sourceFile = 0,
 -         targetDirectory,
 -         targetFilename,
 -         binaryNamespace
 -     };
 - 
 -     static std::optional<Arguments> create (int argc, char* argv[])
 -     {
 -         std::vector<std::string> arguments;
 -         bool verbose = false;
 - 
 -         for (int i = 1; i < argc; ++i)
 -         {
 -             std::string arg { argv[i] };
 - 
 -             if (arg == "-v" || arg == "--verbose")
 -                 verbose = true;
 -             else
 -                 arguments.emplace_back (std::move (arg));
 -         }
 - 
 -         if (arguments.size() != static_cast<size_t> (PositionalArguments::binaryNamespace) + 1)
 -             return std::nullopt;
 - 
 -         return Arguments { std::move (arguments), verbose };
 -     }
 - 
 -     std::string get (PositionalArguments argument) const
 -     {
 -         return arguments[static_cast<size_t> (argument)];
 -     }
 - 
 -     bool isVerbose() const
 -     {
 -         return verbose;
 -     }
 - 
 - private:
 -     Arguments (std::vector<std::string> args, bool verboseIn)
 -         : arguments (std::move (args)), verbose (verboseIn)
 -     {
 -     }
 - 
 -     std::vector<std::string> arguments;
 -     bool verbose = false;
 - };
 - 
 - //==============================================================================
 - int main (int argc, char* argv[])
 - {
 -     const auto arguments = Arguments::create (argc, argv);
 - 
 -     if (! arguments.has_value())
 -     {
 -         std::cout << " Usage: SimpleBinaryBuilder  [-v | --verbose] sourcefile targetdirectory targetfilename namespace"
 -                                                                                                         << std::endl << std::endl
 -                   << " SimpleBinaryBuilder will encode the provided source file into"                   << std::endl
 -                   << " two files called (targetfilename).cpp and (targetfilename).h,"                   << std::endl
 -                   << " which it will write into the specified target directory."                        << std::endl
 -                   << " The target directory will be automatically created if necessary. The binary"     << std::endl
 -                   << " resource will be available in the given namespace."                              << std::endl << std::endl;
 - 
 -         return 0;
 -     }
 - 
 -     const auto currentWorkingDirectory = FileHelpers::getCurrentWorkingDirectory();
 - 
 -     using ArgType = Arguments::PositionalArguments;
 - 
 -     const auto sourceFile = FileHelpers::appendedPaths (currentWorkingDirectory,
 -                                                         StringHelpers::unquoted (arguments->get (ArgType::sourceFile)));
 - 
 -     if (! FileHelpers::exists (sourceFile))
 -     {
 -         std::cerr << "Source file doesn't exist: "
 -                   << sourceFile
 -                   << std::endl << std::endl;
 - 
 -         return 1;
 -     }
 - 
 -     const auto targetDirectory = FileHelpers::appendedPaths (currentWorkingDirectory,
 -                                                              StringHelpers::unquoted (arguments->get (ArgType::targetDirectory)));
 - 
 -     if (! FileHelpers::exists (targetDirectory))
 -     {
 -         if (! FileHelpers::createDirectory (targetDirectory))
 -         {
 -             std::cerr << "Failed to create target directory: " << targetDirectory << std::endl;
 -             return 1;
 -         }
 -     }
 - 
 -     const auto className = StringHelpers::trimmed (arguments->get (ArgType::targetFilename));
 -     const auto binaryNamespace = StringHelpers::trimmed (arguments->get (ArgType::binaryNamespace));
 - 
 -     const auto headerFilePath = FileHelpers::appendedPaths (targetDirectory, className + ".h");
 -     const auto cppFilePath    = FileHelpers::appendedPaths (targetDirectory, className + ".cpp");
 - 
 -     if (arguments->isVerbose())
 -     {
 -         std::cout << "Creating " << headerFilePath
 -                   << " and " << cppFilePath
 -                   << " from file " << sourceFile
 -                   << "..." << std::endl << std::endl;
 -     }
 - 
 -     if (! FileHelpers::deleteFile (headerFilePath))
 -     {
 -         std::cerr << "Failed to remove old header file: " << headerFilePath << std::endl;
 -         return 1;
 -     }
 - 
 -     if (! FileHelpers::deleteFile (cppFilePath))
 -     {
 -         std::cerr << "Failed to remove old source file: " << cppFilePath << std::endl;
 -         return 1;
 -     }
 - 
 -     std::ofstream header (headerFilePath);
 - 
 -     if (! header.is_open())
 -     {
 -         std::cerr << "Failed to open " << headerFilePath << std::endl;
 - 
 -         return 1;
 -     }
 - 
 -     std::ofstream cpp (cppFilePath);
 - 
 -     if (! cpp.is_open())
 -     {
 -         std::cerr << "Failed to open " << headerFilePath << std::endl;
 - 
 -         return 1;
 -     }
 - 
 -     header << "/* (Auto-generated binary data file). */" << std::endl << std::endl
 -            << "#pragma once" << std::endl << std::endl
 -            << "namespace " << binaryNamespace << std::endl
 -            << "{" << std::endl;
 - 
 -     cpp << "/* (Auto-generated binary data file). */" << std::endl << std::endl
 -         << "#include " << std::quoted (className + ".h") << std::endl << std::endl;
 - 
 -     if (! addFile (sourceFile, binaryNamespace, header, cpp, arguments->isVerbose()))
 -         return 1;
 - 
 -     header << "}" << std::endl << std::endl;
 - 
 -     return 0;
 - }
 
 
  |