Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
356c829b
Commit
356c829b
authored
Sep 30, 2015
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
util/StringView: new utility class
parent
ffbb5c48
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
208 additions
and
111 deletions
+208
-111
Makefile.am
Makefile.am
+1
-0
IcyMetaDataParser.cxx
src/IcyMetaDataParser.cxx
+2
-1
Directory.cxx
src/db/plugins/upnp/Directory.cxx
+5
-14
Mpg123DecoderPlugin.cxx
src/decoder/plugins/Mpg123DecoderPlugin.cxx
+2
-1
AsxPlaylistPlugin.cxx
src/playlist/plugins/AsxPlaylistPlugin.cxx
+3
-1
RssPlaylistPlugin.cxx
src/playlist/plugins/RssPlaylistPlugin.cxx
+3
-1
XspfPlaylistPlugin.cxx
src/playlist/plugins/XspfPlaylistPlugin.cxx
+3
-1
ApeLoader.cxx
src/tag/ApeLoader.cxx
+2
-1
ApeLoader.hxx
src/tag/ApeLoader.hxx
+2
-2
ApeReplayGain.cxx
src/tag/ApeReplayGain.cxx
+8
-8
ApeTag.cxx
src/tag/ApeTag.cxx
+8
-8
TagBuilder.cxx
src/tag/TagBuilder.cxx
+12
-22
TagBuilder.hxx
src/tag/TagBuilder.hxx
+3
-2
TagPool.cxx
src/tag/TagPool.cxx
+19
-23
TagPool.hxx
src/tag/TagPool.hxx
+2
-1
TagString.cxx
src/tag/TagString.cxx
+23
-24
TagString.hxx
src/tag/TagString.hxx
+2
-1
StringView.hxx
src/util/StringView.hxx
+108
-0
No files found.
Makefile.am
View file @
356c829b
...
...
@@ -401,6 +401,7 @@ libutil_a_SOURCES = \
src/util/CharUtil.hxx
\
src/util/NumberParser.hxx
\
src/util/StringPointer.hxx
\
src/util/StringView.hxx
\
src/util/AllocatedString.cxx src/util/AllocatedString.hxx
\
src/util/StringUtil.cxx src/util/StringUtil.hxx
\
src/util/WStringUtil.cxx src/util/WStringUtil.hxx
\
...
...
src/IcyMetaDataParser.cxx
View file @
356c829b
...
...
@@ -22,6 +22,7 @@
#include "tag/Tag.hxx"
#include "tag/TagBuilder.hxx"
#include "util/Domain.hxx"
#include "util/StringView.hxx"
#include "Log.hxx"
#include <assert.h>
...
...
@@ -76,7 +77,7 @@ icy_add_item(TagBuilder &tag, TagType type, const char *value)
}
if
(
length
>
0
)
tag
.
AddItem
(
type
,
value
,
length
);
tag
.
AddItem
(
type
,
{
value
,
length
}
);
}
static
void
...
...
src/db/plugins/upnp/Directory.cxx
View file @
356c829b
...
...
@@ -25,6 +25,7 @@
#include "tag/TagBuilder.hxx"
#include "tag/TagTable.hxx"
#include "util/NumberParser.hxx"
#include "util/StringView.hxx"
#include <algorithm>
#include <string>
...
...
@@ -36,23 +37,13 @@ UPnPDirContent::~UPnPDirContent()
/* this destructor exists here just so it won't get inlined */
}
gcc_pure
gcc_nonnull_all
static
bool
CompareStringLiteral
(
const
char
*
literal
,
const
char
*
value
,
size_t
length
)
{
return
length
==
strlen
(
literal
)
&&
memcmp
(
literal
,
value
,
length
)
==
0
;
}
gcc_pure
static
UPnPDirObject
::
ItemClass
ParseItemClass
(
const
char
*
name
,
size_t
length
)
ParseItemClass
(
StringView
name
)
{
if
(
CompareStringLiteral
(
"object.item.audioItem.musicTrack"
,
name
,
length
))
if
(
name
.
EqualsLiteral
(
"object.item.audioItem.musicTrack"
))
return
UPnPDirObject
::
ItemClass
::
MUSIC
;
else
if
(
CompareStringLiteral
(
"object.item.playlistItem"
,
name
,
length
))
else
if
(
name
.
EqualsLiteral
(
"object.item.playlistItem"
))
return
UPnPDirObject
::
ItemClass
::
PLAYLIST
;
else
return
UPnPDirObject
::
ItemClass
::
UNKNOWN
;
...
...
@@ -239,7 +230,7 @@ protected:
break
;
case
CLASS
:
object
.
item_class
=
ParseItemClass
(
s
,
len
);
object
.
item_class
=
ParseItemClass
(
StringView
(
s
,
len
)
);
break
;
}
}
...
...
src/decoder/plugins/Mpg123DecoderPlugin.cxx
View file @
356c829b
...
...
@@ -28,6 +28,7 @@
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/StringView.hxx"
#include "Log.hxx"
#include <mpg123.h>
...
...
@@ -111,7 +112,7 @@ AddTagItem(TagBuilder &tag, TagType type, const mpg123_string &s)
assert
(
s
.
size
>=
s
.
fill
);
assert
(
s
.
fill
>
0
);
tag
.
AddItem
(
type
,
s
.
p
,
s
.
fill
-
1
);
tag
.
AddItem
(
type
,
{
s
.
p
,
s
.
fill
-
1
}
);
}
static
void
...
...
src/playlist/plugins/AsxPlaylistPlugin.cxx
View file @
356c829b
...
...
@@ -24,6 +24,7 @@
#include "tag/TagBuilder.hxx"
#include "util/ASCII.hxx"
#include "util/Error.hxx"
#include "util/StringView.hxx"
#include "lib/expat/ExpatParser.hxx"
#include "Log.hxx"
...
...
@@ -130,7 +131,8 @@ asx_char_data(void *user_data, const XML_Char *s, int len)
case
AsxParser
:
:
ENTRY
:
if
(
parser
->
tag_type
!=
TAG_NUM_OF_ITEM_TYPES
)
parser
->
tag_builder
.
AddItem
(
parser
->
tag_type
,
s
,
len
);
parser
->
tag_builder
.
AddItem
(
parser
->
tag_type
,
StringView
(
s
,
len
));
break
;
}
...
...
src/playlist/plugins/RssPlaylistPlugin.cxx
View file @
356c829b
...
...
@@ -24,6 +24,7 @@
#include "tag/TagBuilder.hxx"
#include "util/ASCII.hxx"
#include "util/Error.hxx"
#include "util/StringView.hxx"
#include "lib/expat/ExpatParser.hxx"
#include "Log.hxx"
...
...
@@ -128,7 +129,8 @@ rss_char_data(void *user_data, const XML_Char *s, int len)
case
RssParser
:
:
ITEM
:
if
(
parser
->
tag_type
!=
TAG_NUM_OF_ITEM_TYPES
)
parser
->
tag_builder
.
AddItem
(
parser
->
tag_type
,
s
,
len
);
parser
->
tag_builder
.
AddItem
(
parser
->
tag_type
,
StringView
(
s
,
len
));
break
;
}
...
...
src/playlist/plugins/XspfPlaylistPlugin.cxx
View file @
356c829b
...
...
@@ -25,6 +25,7 @@
#include "input/InputStream.hxx"
#include "tag/TagBuilder.hxx"
#include "util/Error.hxx"
#include "util/StringView.hxx"
#include "lib/expat/ExpatParser.hxx"
#include "Log.hxx"
...
...
@@ -170,7 +171,8 @@ xspf_char_data(void *user_data, const XML_Char *s, int len)
case
XspfParser
:
:
TRACK
:
if
(
!
parser
->
location
.
empty
()
&&
parser
->
tag_type
!=
TAG_NUM_OF_ITEM_TYPES
)
parser
->
tag_builder
.
AddItem
(
parser
->
tag_type
,
s
,
len
);
parser
->
tag_builder
.
AddItem
(
parser
->
tag_type
,
StringView
(
s
,
len
));
break
;
...
...
src/tag/ApeLoader.cxx
View file @
356c829b
...
...
@@ -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
;
...
...
src/tag/ApeLoader.hxx
View file @
356c829b
...
...
@@ -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.
...
...
src/tag/ApeReplayGain.cxx
View file @
356c829b
...
...
@@ -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
;
};
...
...
src/tag/ApeTag.cxx
View file @
356c829b
...
...
@@ -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
;
};
...
...
src/tag/TagBuilder.cxx
View file @
356c829b
...
...
@@ -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
);
...
...
src/tag/TagBuilder.hxx
View file @
356c829b
...
...
@@ -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
src/tag/TagPool.cxx
View file @
356c829b
...
...
@@ -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
;
}
...
...
src/tag/TagPool.hxx
View file @
356c829b
...
...
@@ -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
);
...
...
src/tag/TagString.cxx
View file @
356c829b
...
...
@@ -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
...
...
src/tag/TagString.hxx
View file @
356c829b
...
...
@@ -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
src/util/StringView.hxx
0 → 100644
View file @
356c829b
/*
* Copyright (C) 2013-2015 Max Kellermann <max@duempel.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef STRING_VIEW_HXX
#define STRING_VIEW_HXX
#include "ConstBuffer.hxx"
#include <string.h>
struct
StringView
:
ConstBuffer
<
char
>
{
StringView
()
=
default
;
constexpr
StringView
(
pointer_type
_data
,
size_type
_size
)
:
ConstBuffer
<
char
>
(
_data
,
_size
)
{}
constexpr
StringView
(
pointer_type
_begin
,
pointer_type
_end
)
:
ConstBuffer
<
char
>
(
_begin
,
_end
-
_begin
)
{}
StringView
(
pointer_type
_data
)
:
ConstBuffer
<
char
>
(
_data
,
_data
!=
nullptr
?
strlen
(
_data
)
:
0
)
{}
StringView
(
std
::
nullptr_t
n
)
:
ConstBuffer
<
char
>
(
n
)
{}
static
constexpr
StringView
Empty
()
{
return
StringView
(
""
,
size_t
(
0
));
}
void
SetEmpty
()
{
data
=
""
;
size
=
0
;
}
gcc_pure
pointer_type
Find
(
char
ch
)
const
{
return
(
pointer_type
)
memchr
(
data
,
ch
,
size
);
}
StringView
&
operator
=
(
std
::
nullptr_t
)
{
data
=
nullptr
;
size
=
0
;
return
*
this
;
}
StringView
&
operator
=
(
pointer_type
_data
)
{
data
=
_data
;
size
=
_data
!=
nullptr
?
strlen
(
_data
)
:
0
;
return
*
this
;
}
gcc_pure
bool
StartsWith
(
StringView
needle
)
const
{
return
size
>=
needle
.
size
&&
memcmp
(
data
,
needle
.
data
,
needle
.
size
)
==
0
;
}
gcc_pure
bool
Equals
(
StringView
other
)
const
{
return
size
==
other
.
size
&&
memcmp
(
data
,
other
.
data
,
size
)
==
0
;
}
template
<
size_t
n
>
bool
EqualsLiteral
(
const
char
(
&
other
)[
n
])
const
{
return
Equals
({
other
,
n
-
1
});
}
gcc_pure
bool
EqualsIgnoreCase
(
StringView
other
)
const
{
return
size
==
other
.
size
&&
strncasecmp
(
data
,
other
.
data
,
size
)
==
0
;
}
template
<
size_t
n
>
bool
EqualsLiteralIgnoreCase
(
const
char
(
&
other
)[
n
])
const
{
return
EqualsIgnoreCase
({
other
,
n
-
1
});
}
};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment