tag/ApeLoader: use class InputStream instead of FILE*
Prepare for APE tag support on userspace NFS/SMB/CIFS mounts.
This commit is contained in:
parent
8a86460b8f
commit
cc5443c38e
@ -1882,10 +1882,15 @@ test_read_tags_SOURCES = test/read_tags.cxx \
|
||||
|
||||
test_ReadApeTags_LDADD = \
|
||||
$(TAG_LIBS) \
|
||||
$(INPUT_LIBS) \
|
||||
$(ARCHIVE_LIBS) \
|
||||
$(FS_LIBS) \
|
||||
$(ICU_LDADD) \
|
||||
libsystem.a \
|
||||
libutil.a
|
||||
test_ReadApeTags_SOURCES = test/ReadApeTags.cxx
|
||||
test_ReadApeTags_SOURCES = \
|
||||
src/Log.cxx src/LogBackend.cxx \
|
||||
test/ReadApeTags.cxx
|
||||
|
||||
if ENABLE_ID3TAG
|
||||
test_dump_rva2_LDADD = \
|
||||
|
@ -20,12 +20,16 @@
|
||||
#include "config.h"
|
||||
#include "ApeLoader.hxx"
|
||||
#include "system/ByteOrder.hxx"
|
||||
#include "fs/FileSystem.hxx"
|
||||
#include "fs/Path.hxx"
|
||||
#include "thread/Mutex.hxx"
|
||||
#include "thread/Cond.hxx"
|
||||
#include "input/InputStream.hxx"
|
||||
#include "input/LocalOpen.hxx"
|
||||
#include "util/StringView.hxx"
|
||||
#include "util/Error.hxx"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
struct ape_footer {
|
||||
@ -37,13 +41,18 @@ struct ape_footer {
|
||||
unsigned char reserved[8];
|
||||
};
|
||||
|
||||
static bool
|
||||
ape_scan_internal(FILE *fp, ApeTagCallback callback)
|
||||
bool
|
||||
tag_ape_scan(InputStream &is, ApeTagCallback callback)
|
||||
{
|
||||
const ScopeLock protect(is.mutex);
|
||||
|
||||
if (!is.KnownSize() || !is.CheapSeeking())
|
||||
return false;
|
||||
|
||||
/* determine if file has an apeV2 tag */
|
||||
struct ape_footer footer;
|
||||
if (fseek(fp, -(long)sizeof(footer), SEEK_END) ||
|
||||
fread(&footer, 1, sizeof(footer), fp) != sizeof(footer) ||
|
||||
if (!is.Seek(is.GetSize() - sizeof(footer), IgnoreError()) ||
|
||||
!is.ReadFull(&footer, sizeof(footer), IgnoreError()) ||
|
||||
memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0 ||
|
||||
FromLE32(footer.version) != 2000)
|
||||
return false;
|
||||
@ -53,7 +62,7 @@ ape_scan_internal(FILE *fp, ApeTagCallback callback)
|
||||
if (remaining <= sizeof(footer) + 10 ||
|
||||
/* refuse to load more than one megabyte of tag data */
|
||||
remaining > 1024 * 1024 ||
|
||||
fseek(fp, -(long)remaining, SEEK_END))
|
||||
!is.Seek(is.GetSize() - remaining, IgnoreError()))
|
||||
return false;
|
||||
|
||||
/* read tag into buffer */
|
||||
@ -61,7 +70,7 @@ ape_scan_internal(FILE *fp, ApeTagCallback callback)
|
||||
assert(remaining > 10);
|
||||
|
||||
char *buffer = new char[remaining];
|
||||
if (fread(buffer, 1, remaining, fp) != remaining) {
|
||||
if (!is.ReadFull(buffer, remaining, IgnoreError())) {
|
||||
delete[] buffer;
|
||||
return false;
|
||||
}
|
||||
@ -104,11 +113,13 @@ ape_scan_internal(FILE *fp, ApeTagCallback callback)
|
||||
bool
|
||||
tag_ape_scan(Path path_fs, ApeTagCallback callback)
|
||||
{
|
||||
FILE *fp = FOpen(path_fs, PATH_LITERAL("rb"));
|
||||
if (fp == nullptr)
|
||||
Mutex mutex;
|
||||
Cond cond;
|
||||
|
||||
std::unique_ptr<InputStream> is(OpenLocalInputStream(path_fs, mutex,
|
||||
cond, IgnoreError()));
|
||||
if (!is)
|
||||
return false;
|
||||
|
||||
bool success = ape_scan_internal(fp, callback);
|
||||
fclose(fp);
|
||||
return success;
|
||||
return tag_ape_scan(*is, callback);
|
||||
}
|
||||
|
@ -28,10 +28,20 @@
|
||||
|
||||
struct StringView;
|
||||
class Path;
|
||||
class InputStream;
|
||||
|
||||
typedef std::function<bool(unsigned long flags, const char *key,
|
||||
StringView value)> ApeTagCallback;
|
||||
|
||||
/**
|
||||
* Scans the APE tag values from a file.
|
||||
*
|
||||
* @return false if the file could not be opened or if no APE tag is
|
||||
* present
|
||||
*/
|
||||
bool
|
||||
tag_ape_scan(InputStream &is, ApeTagCallback callback);
|
||||
|
||||
/**
|
||||
* Scans the APE tag values from a file.
|
||||
*
|
||||
|
@ -105,6 +105,23 @@ tag_ape_import_item(unsigned long flags,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
tag_ape_scan2(InputStream &is,
|
||||
const struct tag_handler *handler, void *handler_ctx)
|
||||
{
|
||||
bool recognized = false;
|
||||
|
||||
auto callback = [handler, handler_ctx, &recognized]
|
||||
(unsigned long flags, const char *key,
|
||||
StringView value) {
|
||||
recognized |= tag_ape_import_item(flags, key, value,
|
||||
handler, handler_ctx);
|
||||
return true;
|
||||
};
|
||||
|
||||
return tag_ape_scan(is, callback) && recognized;
|
||||
}
|
||||
|
||||
bool
|
||||
tag_ape_scan2(Path path_fs,
|
||||
const struct tag_handler *handler, void *handler_ctx)
|
||||
|
@ -23,10 +23,20 @@
|
||||
#include "TagTable.hxx"
|
||||
|
||||
class Path;
|
||||
class InputStream;
|
||||
struct tag_handler;
|
||||
|
||||
extern const struct tag_table ape_tags[];
|
||||
|
||||
/**
|
||||
* Scan the APE tags of a stream.
|
||||
*
|
||||
* @param path_fs the path of the file in filesystem encoding
|
||||
*/
|
||||
bool
|
||||
tag_ape_scan2(InputStream &is,
|
||||
const tag_handler *handler, void *handler_ctx);
|
||||
|
||||
/**
|
||||
* Scan the APE tags of a file.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user