playlist/pls: migrate the line parser to use std::string_view

This commit is contained in:
Max Kellermann
2025-03-10 18:11:59 +01:00
parent 898e0a2bc4
commit 46b461df42

View File

@@ -9,12 +9,14 @@
#include "song/DetachedSong.hxx" #include "song/DetachedSong.hxx"
#include "tag/Builder.hxx" #include "tag/Builder.hxx"
#include "util/ASCII.hxx" #include "util/ASCII.hxx"
#include "util/NumberParser.hxx"
#include "util/StringCompare.hxx"
#include "util/StringSplit.hxx"
#include "util/StringStrip.hxx" #include "util/StringStrip.hxx"
#include "util/DivideString.hxx"
#include <string> #include <string>
#include <stdlib.h> using std::string_view_literals::operator""sv;
static bool static bool
FindPlaylistSection(TextInputStream &is) FindPlaylistSection(TextInputStream &is)
@@ -50,28 +52,27 @@ ParsePls(TextInputStream &is, std::forward_list<DetachedSong> &songs)
std::vector<Entry> entries; std::vector<Entry> entries;
char *line; char *_line;
while ((line = is.ReadLine()) != nullptr) { while ((_line = is.ReadLine()) != nullptr) {
line = Strip(line); std::string_view line = Strip(std::string_view{_line});
if (*line == 0 || *line == ';') if (line.empty() || line.front() == ';')
continue; continue;
if (*line == '[') if (line.front() == '[')
/* another section starts; we only want /* another section starts; we only want
[Playlist], so stop here */ [Playlist], so stop here */
break; break;
const DivideString ds(line, '=', true); auto [name, value] = Split(line, '=');
if (!ds.IsDefined()) if (value.data() == nullptr)
continue; continue;
const char *const name = ds.GetFirst(); name = Strip(name);
const char *const value = ds.GetSecond(); value = Strip(value);
if (StringEqualsCaseASCII(name, "NumberOfEntries")) { if (StringIsEqualIgnoreCase(name, "NumberOfEntries"sv)) {
n_entries = strtoul(value, nullptr, 10); if (!ParseIntegerTo(value, n_entries) || n_entries == 0)
if (n_entries == 0)
/* empty file - nothing remains to be /* empty file - nothing remains to be
done */ done */
return true; return true;
@@ -79,26 +80,29 @@ ParsePls(TextInputStream &is, std::forward_list<DetachedSong> &songs)
if (n_entries > MAX_ENTRIES) if (n_entries > MAX_ENTRIES)
n_entries = MAX_ENTRIES; n_entries = MAX_ENTRIES;
entries.resize(n_entries); entries.resize(n_entries);
} else if (StringEqualsCaseASCII(name, "File", 4)) { } else if (SkipPrefixIgnoreCase(name, "File"sv)) {
unsigned i = strtoul(name + 4, nullptr, 10); unsigned i = 0;
ParseIntegerTo(name, i);
if (i >= 1 && i <= (n_entries > 0 ? n_entries : MAX_ENTRIES)) { if (i >= 1 && i <= (n_entries > 0 ? n_entries : MAX_ENTRIES)) {
if (entries.size() < i) if (entries.size() < i)
entries.resize(i); entries.resize(i);
entries[i - 1].file = value; entries[i - 1].file = value;
} }
} else if (StringEqualsCaseASCII(name, "Title", 5)) { } else if (SkipPrefixIgnoreCase(name, "Title"sv)) {
unsigned i = strtoul(name + 5, nullptr, 10); unsigned i = 0;
ParseIntegerTo(name, i);
if (i >= 1 && i <= (n_entries > 0 ? n_entries : MAX_ENTRIES)) { if (i >= 1 && i <= (n_entries > 0 ? n_entries : MAX_ENTRIES)) {
if (entries.size() < i) if (entries.size() < i)
entries.resize(i); entries.resize(i);
entries[i - 1].title = value; entries[i - 1].title = value;
} }
} else if (StringEqualsCaseASCII(name, "Length", 6)) { } else if (SkipPrefixIgnoreCase(name, "Length"sv)) {
unsigned i = strtoul(name + 6, nullptr, 10); unsigned i = 0;
ParseIntegerTo(name, i);
if (i >= 1 && i <= (n_entries > 0 ? n_entries : MAX_ENTRIES)) { if (i >= 1 && i <= (n_entries > 0 ? n_entries : MAX_ENTRIES)) {
if (entries.size() < i) if (entries.size() < i)
entries.resize(i); entries.resize(i);
entries[i - 1].length = atoi(value); ParseIntegerTo(value, entries[i - 1].length);
} }
} }
} }