From 356c829b767863512da1792c048f6ddbeb8457a3 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 30 Sep 2015 22:03:01 +0200 Subject: util/StringView: new utility class --- src/tag/ApeLoader.cxx | 3 ++- src/tag/ApeLoader.hxx | 4 ++-- src/tag/ApeReplayGain.cxx | 16 ++++++++-------- src/tag/ApeTag.cxx | 16 ++++++++-------- src/tag/TagBuilder.cxx | 34 ++++++++++++---------------------- src/tag/TagBuilder.hxx | 5 +++-- src/tag/TagPool.cxx | 42 +++++++++++++++++++----------------------- src/tag/TagPool.hxx | 3 ++- src/tag/TagString.cxx | 47 +++++++++++++++++++++++------------------------ src/tag/TagString.hxx | 3 ++- 10 files changed, 81 insertions(+), 92 deletions(-) (limited to 'src/tag') 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 #include @@ -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 +struct StringView; class Path; typedef std::function 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 #include 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 @@ -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 @@ -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 +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 #include @@ -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(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 @@ -54,14 +55,14 @@ FindInvalidUTF8(const char *p, const char *const end) * Replace invalid sequences with the question mark. */ static WritableBuffer -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(__invalid); } while (invalid != nullptr); - return { dest, length }; + return { dest, src.size }; } static WritableBuffer -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 -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 -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 cleared = clear_non_printable(p, length); + WritableBuffer 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 +struct StringView; template struct WritableBuffer; gcc_nonnull_all WritableBuffer -FixTagString(const char *p, size_t length); +FixTagString(StringView p); #endif -- cgit v1.2.3