summaryrefslogtreecommitdiff
path: root/source/core/slang-process-util.h
blob: 5d8c358e82943e6b7558d817d780d54ca9276d23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// 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);

    static uint64_t getClockFrequency();

    static uint64_t getClockTick();
};

// -----------------------------------------------------------------------
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