ArgParser.cxx 4.07 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright 2003-2017 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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.
 */

#include "config.h"
Max Kellermann's avatar
Max Kellermann committed
21
#include "ArgParser.hxx"
22
#include "Ack.hxx"
23
#include "Chrono.hxx"
24 25 26

#include <stdlib.h>

27 28
uint32_t
ParseCommandArgU32(const char *s)
29 30
{
	char *test;
31 32 33 34
	auto value = strtoul(s, &test, 10);
	if (test == s || *test != '\0')
		throw FormatProtocolError(ACK_ERROR_ARG,
					  "Integer expected: %s", s);
35

36
	return value;
37 38
}

39 40
int
ParseCommandArgInt(const char *s, int min_value, int max_value)
41 42
{
	char *test;
43 44 45 46
	auto value = strtol(s, &test, 10);
	if (test == s || *test != '\0')
		throw FormatProtocolError(ACK_ERROR_ARG,
					  "Integer expected: %s", s);
47

48 49 50
	if (value < min_value || value > max_value)
		throw FormatProtocolError(ACK_ERROR_ARG,
					  "Number too large: %s", s);
51

52
	return (int)value;
53 54
}

55 56
int
ParseCommandArgInt(const char *s)
57
{
58 59 60
	return ParseCommandArgInt(s,
				  std::numeric_limits<int>::min(),
				  std::numeric_limits<int>::max());
61 62
}

63 64
RangeArg
ParseCommandArgRange(const char *s)
65 66
{
	char *test, *test2;
67 68 69 70
	auto value = strtol(s, &test, 10);
	if (test == s || (*test != '\0' && *test != ':'))
		throw FormatProtocolError(ACK_ERROR_ARG,
					  "Integer or range expected: %s", s);
71

72
	if (value == -1 && *test == 0)
73 74
		/* compatibility with older MPD versions: specifying
		   "-1" makes MPD display the whole list */
75
		return RangeArg::All();
76

77 78 79
	if (value < 0)
		throw FormatProtocolError(ACK_ERROR_ARG,
					  "Number is negative: %s", s);
80

Max Kellermann's avatar
Max Kellermann committed
81
	if (value > std::numeric_limits<int>::max())
82 83
		throw FormatProtocolError(ACK_ERROR_ARG,
					  "Number too large: %s", s);
84

85 86
	RangeArg range;
	range.start = (unsigned)value;
87 88 89

	if (*test == ':') {
		value = strtol(++test, &test2, 10);
90 91 92 93
		if (*test2 != '\0')
			throw FormatProtocolError(ACK_ERROR_ARG,
						  "Integer or range expected: %s",
						  s);
94 95

		if (test == test2)
96
			value = std::numeric_limits<int>::max();
97

98 99 100
		if (value < 0)
			throw FormatProtocolError(ACK_ERROR_ARG,
						  "Number is negative: %s", s);
101 102


Max Kellermann's avatar
Max Kellermann committed
103
		if (value > std::numeric_limits<int>::max())
104 105
			throw FormatProtocolError(ACK_ERROR_ARG,
						  "Number too large: %s", s);
106

107
		range.end = (unsigned)value;
108
	} else {
109
		range.end = (unsigned)value + 1;
110 111
	}

112
	return range;
113 114
}

115 116
unsigned
ParseCommandArgUnsigned(const char *s, unsigned max_value)
117 118
{
	char *endptr;
119 120 121 122
	auto value = strtoul(s, &endptr, 10);
	if (endptr == s || *endptr != 0)
		throw FormatProtocolError(ACK_ERROR_ARG,
					  "Integer expected: %s", s);
123

124 125 126
	if (value > max_value)
		throw FormatProtocolError(ACK_ERROR_ARG,
					  "Number too large: %s", s);
127

128
	return (unsigned)value;
129 130
}

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

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

147
	return !!value;
148 149
}

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

159
	return value;
160
}
161

162 163
SongTime
ParseCommandArgSongTime(const char *s)
164
{
165 166
	auto value = ParseCommandArgFloat(s);
	return SongTime::FromS(value);
167 168
}

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