https://github.com/shader-slang/slang
Raw File
Tip revision: 0b6321b3f08c48e37e6b8256d420f05d9727fb5a authored by Tim Foley on 13 September 2019, 17:41:11 UTC
Revisions to "new" Slang API based on use in Falcor (#1052)
Tip revision: 0b6321b
slang-process-util.h
// slang-process-util.h
#ifndef SLANG_PROCESS_UTIL_H
#define SLANG_PROCESS_UTIL_H

#include "slang-string.h"
#include "slang-list.h"

namespace Slang {

struct CommandLine
{
    enum class ExecutableType
    {
        Unknown,                    ///< The executable is not specified 
        Path,                       ///< The executable is set as a path
        Filename,                   ///< The executable is set as a filename
    };

    enum class ArgType
    {
        Escaped,
        Unescaped,
    };

    struct Arg
    {
        ArgType type;               ///< How to interpret the argument value
        String value;               ///< The argument value
    };

        /// Add args - assumed unescaped
    void addArg(const String& in) { m_args.add(Arg{ArgType::Unescaped, in}); }
    void addArgs(const String* args, Int argsCount) { for (Int i = 0; i < argsCount; ++i) addArg(args[i]); }

        /// Add args - all assumed unescaped
    void addArgs(const Arg* args, Int argCount) { m_args.addRange(args, argCount); }

        /// Add an escaped arg
    void addEscapedArg(const String& in) { m_args.add(Arg{ArgType::Escaped, in}); }
    void addEscapedArgs(const String* args, Int argsCount) { for (Int i = 0; i < argsCount; ++i) addEscapedArg(args[i]); }

        /// Find the index of an arg which is exact match for slice
    SLANG_INLINE Index findArgIndex(const UnownedStringSlice& slice) const;

        /// Set the executable path
    void setExecutablePath(const String& path) { m_executableType = ExecutableType::Path; m_executable = path; }
    void setExecutableFilename(const String& filename) { m_executableType = ExecutableType::Filename; m_executable = filename; }

        /// For handling args where the switch is placed directly in front of the path 
    SLANG_INLINE void addPrefixPathArg(const char* prefix, const String& path, const char* pathPostfix = nullptr);

        /// Get the total number of args
    SLANG_FORCE_INLINE Index getArgCount() const { return m_args.getCount(); }

        /// Reset to the initial state
    void reset() { *this = CommandLine();  }

        /// Ctor
    CommandLine():m_executableType(ExecutableType::Unknown) {}

    ExecutableType m_executableType;    ///< How the executable is specified
    String m_executable;                ///< Executable to run. Note that the executable is never escaped.
    List<Arg> m_args;                   ///< The arguments  
};

struct ExecuteResult
{
    void init()
    {
        resultCode = 0;
        standardOutput = String();
        standardError = String();
    }

    typedef int ResultCode;
    ResultCode resultCode;
    Slang::String standardOutput;
    Slang::String standardError;
};

struct ProcessUtil
{
        /// Get the suffix used on this platform
    static UnownedStringSlice getExecutableSuffix();

        /// Output how the command line is executed on the target (with escaping and the such like)
    static String getCommandLineString(const CommandLine& commandLine);

        /// Execute the command line 
    static SlangResult execute(const CommandLine& commandLine, ExecuteResult& outExecuteResult);

        /// Append text escaped for using on a command line
    static void appendCommandLineEscaped(const UnownedStringSlice& slice, StringBuilder& out);
};

// -----------------------------------------------------------------------
SLANG_INLINE Index CommandLine::findArgIndex(const UnownedStringSlice& slice) const
{
    const Index count = m_args.getCount();

    for (Index i = 0; i < count; ++i)
    {
        const auto& arg = m_args[i];
        if (arg.value == slice)
        {
            return i;
        }
    }
    return -1;
}

// -----------------------------------------------------------------------
SLANG_INLINE void CommandLine::addPrefixPathArg(const char* prefix, const String& path, const char* pathPostfix)
{
    StringBuilder builder;
    builder << prefix;
    if (pathPostfix)
    {
        // Work out the path with the postfix
        StringBuilder fullPath;
        fullPath << path << pathPostfix;  
        ProcessUtil::appendCommandLineEscaped(fullPath.getUnownedSlice(), builder);
    }
    else
    {
        ProcessUtil::appendCommandLineEscaped(path.getUnownedSlice(), builder);
    }

    // This arg doesn't need subsequent escaping
    addEscapedArg(builder);
}

}

#endif // SLANG_PROCESS_UTIL_H
back to top