summaryrefslogtreecommitdiff
path: root/archived/projt-launcher/launcher/launch/LaunchVariableExpander.cpp
blob: 175b0031159cd8403fd547903ddc6fc439583ff5 (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
// SPDX-License-Identifier: GPL-3.0-only
// SPDX-FileCopyrightText: 2026 Project Tick
// SPDX-FileContributor: Project Tick Team
/*
 *  ProjT Launcher - Minecraft Launcher
 *  Copyright (C) 2026 Project Tick
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, version 3.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, write to the Free Software Foundation,
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "LaunchVariableExpander.hpp"

namespace projt::launch
{
	QString LaunchVariableExpander::expand(const QString& input, const QProcessEnvironment& env) const
	{
		QString output = input;

		enum class Mode
		{
			Idle,
			Sigil,
			Name,
			Brace
		};

		Mode mode	   = Mode::Idle;
		int tokenStart = -1;

		for (int idx = 0; idx < output.length();)
		{
			const QChar c = output.at(idx++);
			switch (mode)
			{
				case Mode::Idle:
					if (c == '$')
					{
						mode = Mode::Sigil;
					}
					break;
				case Mode::Sigil:
					if (c == '{')
					{
						mode	   = Mode::Brace;
						tokenStart = idx;
					}
					else if (c.isLetterOrNumber() || c == '_')
					{
						mode	   = Mode::Name;
						tokenStart = idx - 1;
					}
					else
					{
						mode = Mode::Idle;
					}
					break;
				case Mode::Brace:
					if (c == '}')
					{
						const auto key	 = output.mid(tokenStart, idx - 1 - tokenStart);
						const auto value = env.value(key, "");
						if (!value.isEmpty())
						{
							output.replace(tokenStart - 2, idx - tokenStart + 2, value);
							idx = tokenStart - 2 + value.length();
						}
						mode = Mode::Idle;
					}
					break;
				case Mode::Name:
					if (!c.isLetterOrNumber() && c != '_')
					{
						const auto key	 = output.mid(tokenStart, idx - tokenStart - 1);
						const auto value = env.value(key, "");
						if (!value.isEmpty())
						{
							output.replace(tokenStart - 1, idx - tokenStart, value);
							idx = tokenStart - 1 + value.length();
						}
						mode = Mode::Idle;
					}
					break;
			}
		}

		if (mode == Mode::Name)
		{
			const auto value = env.value(output.mid(tokenStart), "");
			if (!value.isEmpty())
			{
				output.replace(tokenStart - 1, output.length() - tokenStart + 1, value);
			}
		}

		return output;
	}
} // namespace projt::launch