ArgParser.cxx 4.05 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright 2003-2021 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 * http://www.musicpd.org
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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.
 */

Max Kellermann's avatar
Max Kellermann committed
20
#include "ArgParser.hxx"
21
#include "RangeArg.hxx"
22
#include "Ack.hxx"
23
#include "Chrono.hxx"
24
#include "util/NumberParser.hxx"
25

26
#include <stdio.h>
27 28
#include <stdlib.h>

29 30 31 32 33
static inline ProtocolError
MakeArgError(const char *msg, const char *value) noexcept
{
	char buffer[256];
	snprintf(buffer, sizeof(buffer), "%s: %s", msg, value);
Rosen Penev's avatar
Rosen Penev committed
34
	return {ACK_ERROR_ARG, buffer};
35 36
}

37 38
uint32_t
ParseCommandArgU32(const char *s)
39 40
{
	char *test;
41 42
	auto value = strtoul(s, &test, 10);
	if (test == s || *test != '\0')
43
		throw MakeArgError("Integer expected", s);
44

45
	return value;
46 47
}

48 49
int
ParseCommandArgInt(const char *s, int min_value, int max_value)
50 51
{
	char *test;
52 53
	auto value = strtol(s, &test, 10);
	if (test == s || *test != '\0')
54
		throw MakeArgError("Integer expected", s);
55

56
	if (value < min_value || value > max_value)
57
		throw MakeArgError("Number too large", s);
58

59
	return (int)value;
60 61
}

62 63
int
ParseCommandArgInt(const char *s)
64
{
65 66 67
	return ParseCommandArgInt(s,
				  std::numeric_limits<int>::min(),
				  std::numeric_limits<int>::max());
68 69
}

70 71
RangeArg
ParseCommandArgRange(const char *s)
72 73
{
	char *test, *test2;
74 75
	auto value = strtol(s, &test, 10);
	if (test == s || (*test != '\0' && *test != ':'))
76
		throw MakeArgError("Integer or range expected", s);
77

78
	if (value == -1 && *test == 0)
79 80
		/* compatibility with older MPD versions: specifying
		   "-1" makes MPD display the whole list */
81
		return RangeArg::All();
82

83
	if (value < 0)
84
		throw MakeArgError("Number is negative", s);
85

86
	if (value > std::numeric_limits<int>::max())
87
		throw MakeArgError("Number too large", s);
88

89 90
	RangeArg range;
	range.start = (unsigned)value;
91 92 93

	if (*test == ':') {
		value = strtol(++test, &test2, 10);
94
		if (*test2 != '\0')
95
			throw MakeArgError("Integer or range expected", s);
96 97

		if (test == test2)
98
			return RangeArg::OpenEnded(range.start);
99

100
		if (value < 0)
101
			throw MakeArgError("Number is negative", s);
102 103


104
		if (value > std::numeric_limits<int>::max())
105
			throw MakeArgError("Number too large", s);
106

107
		range.end = (unsigned)value;
108
	} else {
109
		return RangeArg::Single(range.start);
110 111
	}

112
	if (!range.IsWellFormed())
113
		throw MakeArgError("Malformed range", s);
114

115
	return range;
116 117
}

118 119
unsigned
ParseCommandArgUnsigned(const char *s, unsigned max_value)
120 121
{
	char *endptr;
122 123
	auto value = strtoul(s, &endptr, 10);
	if (endptr == s || *endptr != 0)
124
		throw MakeArgError("Integer expected", s);
125

126
	if (value > max_value)
127
		throw MakeArgError("Number too large", s);
128

129
	return (unsigned)value;
130 131
}

132 133
unsigned
ParseCommandArgUnsigned(const char *s)
134
{
135 136
	return ParseCommandArgUnsigned(s,
				       std::numeric_limits<unsigned>::max());
137 138
}

139
bool
140
ParseCommandArgBool(const char *s)
141 142
{
	char *endptr;
143 144
	auto value = strtol(s, &endptr, 10);
	if (endptr == s || *endptr != 0 || (value != 0 && value != 1))
145
		throw MakeArgError("Boolean (0/1) expected", s);
146

147
	return !!value;
148 149
}

150 151
float
ParseCommandArgFloat(const char *s)
152 153
{
	char *endptr;
154
	auto value = ParseFloat(s, &endptr);
155
	if (endptr == s || *endptr != 0)
156
		throw MakeArgError("Float expected", s);
157

158
	return value;
159
}
160

161 162
SongTime
ParseCommandArgSongTime(const char *s)
163
{
164
	auto value = ParseCommandArgFloat(s);
165
	if (value < 0)
166
		throw MakeArgError("Negative value not allowed", s);
167

168
	return SongTime::FromS(value);
169 170
}

171 172
SignedSongTime
ParseCommandArgSignedSongTime(const char *s)
173
{
174
	auto value = ParseCommandArgFloat(s);
175
	return SignedSongTime::FromS(value);
176
}