aboutsummaryrefslogtreecommitdiffstats
path: root/src/tag
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2015-09-30 22:03:01 +0200
committerMax Kellermann <max@duempel.org>2015-09-30 22:21:46 +0200
commit356c829b767863512da1792c048f6ddbeb8457a3 (patch)
tree7b71365eb164719ddf12d081766520ee4938bc28 /src/tag
parentffbb5c48ed3edaeb72b26b61637eb3bd1cea9e32 (diff)
downloadmpd-356c829b767863512da1792c048f6ddbeb8457a3.tar.gz
mpd-356c829b767863512da1792c048f6ddbeb8457a3.tar.xz
mpd-356c829b767863512da1792c048f6ddbeb8457a3.zip
util/StringView: new utility class
Diffstat (limited to 'src/tag')
-rw-r--r--src/tag/ApeLoader.cxx3
-rw-r--r--src/tag/ApeLoader.hxx4
-rw-r--r--src/tag/ApeReplayGain.cxx16
-rw-r--r--src/tag/ApeTag.cxx16
-rw-r--r--src/tag/TagBuilder.cxx34
-rw-r--r--src/tag/TagBuilder.hxx5
-rw-r--r--src/tag/TagPool.cxx42
-rw-r--r--src/tag/TagPool.hxx3
-rw-r--r--src/tag/TagString.cxx47
-rw-r--r--src/tag/TagString.hxx3
10 files changed, 81 insertions, 92 deletions
diff --git a/src/tag/ApeLoader.cxx b/src/tag/ApeLoader.cxx
index 8c89f34c9..c42d088a8 100644
--- a/src/tag/ApeLoader.cxx
+++ b/src/tag/ApeLoader.cxx
@@ -21,6 +21,7 @@
#include "ApeLoader.hxx"
#include "system/ByteOrder.hxx"
#include "fs/FileSystem.hxx"
+#include "util/StringView.hxx"
#include <stdint.h>
#include <assert.h>
@@ -89,7 +90,7 @@ ape_scan_internal(FILE *fp, ApeTagCallback callback)
if (remaining < size)
break;
- if (!callback(flags, key, p, size))
+ if (!callback(flags, key, {p, size}))
break;
p += size;
diff --git a/src/tag/ApeLoader.hxx b/src/tag/ApeLoader.hxx
index 1bdfe692d..4587ff063 100644
--- a/src/tag/ApeLoader.hxx
+++ b/src/tag/ApeLoader.hxx
@@ -26,11 +26,11 @@
#include <stddef.h>
+struct StringView;
class Path;
typedef std::function<bool(unsigned long flags, const char *key,
- const char *value,
- size_t value_length)> ApeTagCallback;
+ StringView value)> ApeTagCallback;
/**
* Scans the APE tag values from a file.
diff --git a/src/tag/ApeReplayGain.cxx b/src/tag/ApeReplayGain.cxx
index 139d44d1f..883885369 100644
--- a/src/tag/ApeReplayGain.cxx
+++ b/src/tag/ApeReplayGain.cxx
@@ -21,15 +21,16 @@
#include "ApeReplayGain.hxx"
#include "ApeLoader.hxx"
#include "ReplayGain.hxx"
-#include "util/ASCII.hxx"
#include "fs/Path.hxx"
+#include "util/ASCII.hxx"
+#include "util/StringView.hxx"
#include <string.h>
#include <stdlib.h>
static bool
replay_gain_ape_callback(unsigned long flags, const char *key,
- const char *_value, size_t value_length,
+ StringView _value,
ReplayGainInfo &info)
{
/* we only care about utf-8 text tags */
@@ -37,11 +38,11 @@ replay_gain_ape_callback(unsigned long flags, const char *key,
return false;
char value[16];
- if (value_length >= sizeof(value))
+ if (_value.size >= sizeof(value))
return false;
- memcpy(value, _value, value_length);
- value[value_length] = 0;
+ memcpy(value, _value.data, _value.size);
+ value[_value.size] = 0;
return ParseReplayGainTag(info, key, value);
}
@@ -53,10 +54,9 @@ replay_gain_ape_read(Path path_fs, ReplayGainInfo &info)
auto callback = [&info, &found]
(unsigned long flags, const char *key,
- const char *value,
- size_t value_length) {
+ StringView value) {
found |= replay_gain_ape_callback(flags, key,
- value, value_length,
+ value,
info);
return true;
};
diff --git a/src/tag/ApeTag.cxx b/src/tag/ApeTag.cxx
index 49ae7a036..81318a771 100644
--- a/src/tag/ApeTag.cxx
+++ b/src/tag/ApeTag.cxx
@@ -24,6 +24,7 @@
#include "TagTable.hxx"
#include "TagHandler.hxx"
#include "fs/Path.hxx"
+#include "util/StringView.hxx"
#include <string>
@@ -75,17 +76,18 @@ ForEachValue(const char *value, const char *end, C &&callback)
*/
static bool
tag_ape_import_item(unsigned long flags,
- const char *key, const char *value, size_t value_length,
+ const char *key, StringView value,
const struct tag_handler *handler, void *handler_ctx)
{
/* we only care about utf-8 text tags */
if ((flags & (0x3 << 1)) != 0)
return false;
- const char *const end = value + value_length;
+ const auto begin = value.begin();
+ const auto end = value.end();
if (handler->pair != nullptr)
- ForEachValue(value, end, [handler, handler_ctx,
+ ForEachValue(begin, end, [handler, handler_ctx,
key](const char *_value) {
handler->pair(key, _value, handler_ctx);
});
@@ -94,8 +96,8 @@ tag_ape_import_item(unsigned long flags,
if (type == TAG_NUM_OF_ITEM_TYPES)
return false;
- ForEachValue(value, end, [handler, handler_ctx,
- type](const char *_value) {
+ ForEachValue(begin, end, [handler, handler_ctx,
+ type](const char *_value) {
tag_handler_invoke_tag(handler, handler_ctx,
type, _value);
});
@@ -111,10 +113,8 @@ tag_ape_scan2(Path path_fs,
auto callback = [handler, handler_ctx, &recognized]
(unsigned long flags, const char *key,
- const char *value,
- size_t value_length) {
+ StringView value) {
recognized |= tag_ape_import_item(flags, key, value,
- value_length,
handler, handler_ctx);
return true;
};
diff --git a/src/tag/TagBuilder.cxx b/src/tag/TagBuilder.cxx
index 4ce50cc4c..82d99006a 100644
--- a/src/tag/TagBuilder.cxx
+++ b/src/tag/TagBuilder.cxx
@@ -24,6 +24,7 @@
#include "TagString.hxx"
#include "Tag.hxx"
#include "util/WritableBuffer.hxx"
+#include "util/StringView.hxx"
#include <array>
@@ -189,22 +190,16 @@ TagBuilder::Complement(const Tag &other)
}
inline void
-TagBuilder::AddItemInternal(TagType type, const char *value, size_t length)
+TagBuilder::AddItemInternal(TagType type, StringView value)
{
-#if !CLANG_CHECK_VERSION(3,6)
- /* disabled on clang due to -Wtautological-pointer-compare */
- assert(value != nullptr);
-#endif
- assert(length > 0);
+ assert(!value.IsEmpty());
- auto f = FixTagString(value, length);
- if (!f.IsNull()) {
- value = f.data;
- length = f.size;
- }
+ auto f = FixTagString(value);
+ if (!f.IsNull())
+ value = { f.data, f.size };
tag_pool_lock.lock();
- auto i = tag_pool_get_item(type, value, length);
+ auto i = tag_pool_get_item(type, value);
tag_pool_lock.unlock();
free(f.data);
@@ -213,17 +208,12 @@ TagBuilder::AddItemInternal(TagType type, const char *value, size_t length)
}
void
-TagBuilder::AddItem(TagType type, const char *value, size_t length)
+TagBuilder::AddItem(TagType type, StringView value)
{
-#if !CLANG_CHECK_VERSION(3,6)
- /* disabled on clang due to -Wtautological-pointer-compare */
- assert(value != nullptr);
-#endif
-
- if (length == 0 || !IsTagEnabled(type))
+ if (value.IsEmpty() || !IsTagEnabled(type))
return;
- AddItemInternal(type, value, length);
+ AddItemInternal(type, value);
}
void
@@ -234,14 +224,14 @@ TagBuilder::AddItem(TagType type, const char *value)
assert(value != nullptr);
#endif
- AddItem(type, value, strlen(value));
+ AddItem(type, StringView(value));
}
void
TagBuilder::AddEmptyItem(TagType type)
{
tag_pool_lock.lock();
- auto i = tag_pool_get_item(type, "", 0);
+ auto i = tag_pool_get_item(type, StringView::Empty());
tag_pool_lock.unlock();
items.push_back(i);
diff --git a/src/tag/TagBuilder.hxx b/src/tag/TagBuilder.hxx
index 738caa6cd..08c66d0b3 100644
--- a/src/tag/TagBuilder.hxx
+++ b/src/tag/TagBuilder.hxx
@@ -28,6 +28,7 @@
#include <stddef.h>
+struct StringView;
struct TagItem;
struct Tag;
@@ -141,7 +142,7 @@ public:
* @param length the length of #value
*/
gcc_nonnull_all
- void AddItem(TagType type, const char *value, size_t length);
+ void AddItem(TagType type, StringView value);
/**
* Appends a new tag item.
@@ -171,7 +172,7 @@ public:
private:
gcc_nonnull_all
- void AddItemInternal(TagType type, const char *value, size_t length);
+ void AddItemInternal(TagType type, StringView value);
};
#endif
diff --git a/src/tag/TagPool.cxx b/src/tag/TagPool.cxx
index 0280948fd..88b2ba333 100644
--- a/src/tag/TagPool.cxx
+++ b/src/tag/TagPool.cxx
@@ -22,6 +22,7 @@
#include "TagItem.hxx"
#include "util/Cast.hxx"
#include "util/VarSize.hxx"
+#include "util/StringView.hxx"
#include <assert.h>
#include <string.h>
@@ -37,39 +38,37 @@ struct TagPoolSlot {
TagItem item;
TagPoolSlot(TagPoolSlot *_next, TagType type,
- const char *value, size_t length)
+ StringView value)
:next(_next), ref(1) {
item.type = type;
- memcpy(item.value, value, length);
- item.value[length] = 0;
+ memcpy(item.value, value.data, value.size);
+ item.value[value.size] = 0;
}
static TagPoolSlot *Create(TagPoolSlot *_next, TagType type,
- const char *value, size_t length);
+ StringView value);
} gcc_packed;
TagPoolSlot *
TagPoolSlot::Create(TagPoolSlot *_next, TagType type,
- const char *value, size_t length)
+ StringView value)
{
TagPoolSlot *dummy;
return NewVarSize<TagPoolSlot>(sizeof(dummy->item.value),
- length + 1,
+ value.size + 1,
_next, type,
- value, length);
+ value);
}
static TagPoolSlot *slots[NUM_SLOTS];
static inline unsigned
-calc_hash_n(TagType type, const char *p, size_t length)
+calc_hash(TagType type, StringView p)
{
unsigned hash = 5381;
- assert(p != nullptr);
-
- while (length-- > 0)
- hash = (hash << 5) + hash + *p++;
+ for (auto ch : p)
+ hash = (hash << 5) + hash + ch;
return hash ^ type;
}
@@ -97,9 +96,9 @@ tag_item_to_slot(TagItem *item)
}
static inline TagPoolSlot **
-tag_value_slot_p(TagType type, const char *value, size_t length)
+tag_value_slot_p(TagType type, StringView value)
{
- return &slots[calc_hash_n(type, value, length) % NUM_SLOTS];
+ return &slots[calc_hash(type, value) % NUM_SLOTS];
}
static inline TagPoolSlot **
@@ -109,13 +108,12 @@ tag_value_slot_p(TagType type, const char *value)
}
TagItem *
-tag_pool_get_item(TagType type, const char *value, size_t length)
+tag_pool_get_item(TagType type, StringView value)
{
- auto slot_p = tag_value_slot_p(type, value, length);
+ auto slot_p = tag_value_slot_p(type, value);
for (auto slot = *slot_p; slot != nullptr; slot = slot->next) {
if (slot->item.type == type &&
- length == strlen(slot->item.value) &&
- memcmp(value, slot->item.value, length) == 0 &&
+ value.Equals(slot->item.value) &&
slot->ref < 0xff) {
assert(slot->ref > 0);
++slot->ref;
@@ -123,7 +121,7 @@ tag_pool_get_item(TagType type, const char *value, size_t length)
}
}
- auto slot = TagPoolSlot::Create(*slot_p, type, value, length);
+ auto slot = TagPoolSlot::Create(*slot_p, type, value);
*slot_p = slot;
return &slot->item;
}
@@ -141,11 +139,9 @@ tag_pool_dup_item(TagItem *item)
} else {
/* the reference counter overflows above 0xff;
duplicate the item, and start with 1 */
- size_t length = strlen(item->value);
- auto slot_p = tag_value_slot_p(item->type,
- item->value, length);
+ auto slot_p = tag_value_slot_p(item->type, item->value);
slot = TagPoolSlot::Create(*slot_p, item->type,
- item->value, strlen(item->value));
+ item->value);
*slot_p = slot;
return &slot->item;
}
diff --git a/src/tag/TagPool.hxx b/src/tag/TagPool.hxx
index 7fba85b54..7b4b5dadf 100644
--- a/src/tag/TagPool.hxx
+++ b/src/tag/TagPool.hxx
@@ -26,9 +26,10 @@
extern Mutex tag_pool_lock;
struct TagItem;
+struct StringView;
TagItem *
-tag_pool_get_item(TagType type, const char *value, size_t length);
+tag_pool_get_item(TagType type, StringView value);
TagItem *
tag_pool_dup_item(TagItem *item);
diff --git a/src/tag/TagString.cxx b/src/tag/TagString.cxx
index 85227de24..d30a07a27 100644
--- a/src/tag/TagString.cxx
+++ b/src/tag/TagString.cxx
@@ -21,6 +21,7 @@
#include "TagString.hxx"
#include "util/Alloc.hxx"
#include "util/WritableBuffer.hxx"
+#include "util/StringView.hxx"
#include "util/UTF8.hxx"
#include <assert.h>
@@ -54,14 +55,14 @@ FindInvalidUTF8(const char *p, const char *const end)
* Replace invalid sequences with the question mark.
*/
static WritableBuffer<char>
-patch_utf8(const char *src, size_t length, const char *_invalid)
+patch_utf8(StringView src, const char *_invalid)
{
/* duplicate the string, and replace invalid bytes in that
buffer */
- char *dest = (char *)xmemdup(src, length);
- char *const end = dest + length;
+ char *dest = (char *)xmemdup(src.data, src.size);
+ char *const end = dest + src.size;
- char *invalid = dest + (_invalid - src);
+ char *invalid = dest + (_invalid - src.data);
do {
*invalid = '?';
@@ -69,19 +70,19 @@ patch_utf8(const char *src, size_t length, const char *_invalid)
invalid = const_cast<char *>(__invalid);
} while (invalid != nullptr);
- return { dest, length };
+ return { dest, src.size };
}
static WritableBuffer<char>
-fix_utf8(const char *str, size_t length)
+fix_utf8(StringView p)
{
/* check if the string is already valid UTF-8 */
- const char *invalid = FindInvalidUTF8(str, str + length);
+ const char *invalid = FindInvalidUTF8(p.begin(), p.end());
if (invalid == nullptr)
return nullptr;
/* no, broken - patch invalid sequences */
- return patch_utf8(str, length, invalid);
+ return patch_utf8(p, invalid);
}
static bool
@@ -91,11 +92,11 @@ char_is_non_printable(unsigned char ch)
}
static const char *
-find_non_printable(const char *p, size_t length)
+find_non_printable(StringView p)
{
- for (size_t i = 0; i < length; ++i)
- if (char_is_non_printable(p[i]))
- return p + i;
+ for (const char &ch : p)
+ if (char_is_non_printable(ch))
+ return &ch;
return nullptr;
}
@@ -105,31 +106,29 @@ find_non_printable(const char *p, size_t length)
* Returns nullptr if nothing needs to be cleared.
*/
static WritableBuffer<char>
-clear_non_printable(const char *p, size_t length)
+clear_non_printable(StringView src)
{
- const char *first = find_non_printable(p, length);
+ const char *first = find_non_printable(src);
if (first == nullptr)
return nullptr;
- char *dest = (char *)xmemdup(p, length);
+ char *dest = (char *)xmemdup(src.data, src.size);
- for (size_t i = first - p; i < length; ++i)
+ for (size_t i = first - src.data; i < src.size; ++i)
if (char_is_non_printable(dest[i]))
dest[i] = ' ';
- return { dest, length };
+ return { dest, src.size };
}
WritableBuffer<char>
-FixTagString(const char *p, size_t length)
+FixTagString(StringView p)
{
- auto utf8 = fix_utf8(p, length);
- if (!utf8.IsNull()) {
- p = utf8.data;
- length = utf8.size;
- }
+ auto utf8 = fix_utf8(p);
+ if (!utf8.IsNull())
+ p = {utf8.data, utf8.size};
- WritableBuffer<char> cleared = clear_non_printable(p, length);
+ WritableBuffer<char> cleared = clear_non_printable(p);
if (cleared.IsNull())
cleared = utf8;
else
diff --git a/src/tag/TagString.hxx b/src/tag/TagString.hxx
index f4cba9a40..53fbc7abd 100644
--- a/src/tag/TagString.hxx
+++ b/src/tag/TagString.hxx
@@ -25,10 +25,11 @@
#include <stddef.h>
+struct StringView;
template<typename T> struct WritableBuffer;
gcc_nonnull_all
WritableBuffer<char>
-FixTagString(const char *p, size_t length);
+FixTagString(StringView p);
#endif