mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-17 21:05:46 -04:00
Initial community commit
This commit is contained in:
1
Src/replicant/nsapev2/VERSION
Normal file
1
Src/replicant/nsapev2/VERSION
Normal file
@ -0,0 +1 @@
|
||||
1.2
|
20
Src/replicant/nsapev2/flags.h
Normal file
20
Src/replicant/nsapev2/flags.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "foundation/error.h"
|
||||
namespace APEv2
|
||||
{
|
||||
/*
|
||||
http://wiki.hydrogenaudio.org/index.php?title=Ape_Tags_Flags
|
||||
*/
|
||||
enum
|
||||
{
|
||||
/* flags for header or item */
|
||||
FLAG_READONLY = 1,
|
||||
|
||||
/* header/footer specific flags */
|
||||
FLAG_HEADER_HAS_HEADER = (1 << 31),
|
||||
FLAG_HEADER_NO_FOOTER = (1 << 30),
|
||||
FLAG_HEADER_IS_HEADER = (1 << 29),
|
||||
FLAG_HEADER_ENCODE_MASK = FLAG_READONLY|FLAG_HEADER_HAS_HEADER|FLAG_HEADER_NO_FOOTER,
|
||||
};
|
||||
|
||||
}
|
91
Src/replicant/nsapev2/header.cpp
Normal file
91
Src/replicant/nsapev2/header.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "header.h"
|
||||
#include "flags.h"
|
||||
#include "util.h"
|
||||
#include "nu/ByteReader.h"
|
||||
#include "nu/ByteWriter.h"
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char apev2_preamble[] = { 'A', 'P', 'E', 'T', 'A', 'G', 'E', 'X' };
|
||||
APEv2::Header::Header()
|
||||
{
|
||||
memcpy(preamble, apev2_preamble, 8);
|
||||
version=2000;
|
||||
size=0;
|
||||
items=0;
|
||||
flags=0;
|
||||
reserved=0;
|
||||
}
|
||||
|
||||
APEv2::Header::Header(const void *data)
|
||||
{
|
||||
bytereader_value_t byte_reader;
|
||||
bytereader_init(&byte_reader, data, Header::SIZE);
|
||||
|
||||
bytereader_read_n(&byte_reader, preamble, 8);
|
||||
version=bytereader_read_u32_le(&byte_reader);
|
||||
size=bytereader_read_u32_le(&byte_reader);
|
||||
items=bytereader_read_u32_le(&byte_reader);
|
||||
flags=bytereader_read_u32_le(&byte_reader);
|
||||
bytereader_read_n(&byte_reader, &reserved, 8);
|
||||
}
|
||||
|
||||
uint32_t APEv2::Header::GetFlags() const
|
||||
{
|
||||
return flags;
|
||||
}
|
||||
|
||||
bool APEv2::Header::Valid() const
|
||||
{
|
||||
return !memcmp(preamble, apev2_preamble, 8) && reserved == 0;
|
||||
}
|
||||
|
||||
uint32_t APEv2::Header::TagSize() const
|
||||
{
|
||||
size_t size = this->size;
|
||||
if (IsHeader() && HasFooter())
|
||||
size+=SIZE;
|
||||
if (IsFooter() && HasHeader())
|
||||
size+=SIZE;
|
||||
|
||||
if (size > ULONG_MAX)
|
||||
return 0;
|
||||
|
||||
return (uint32_t)size;
|
||||
}
|
||||
|
||||
bool APEv2::Header::HasHeader() const
|
||||
{
|
||||
return !!(flags & FLAG_HEADER_HAS_HEADER);
|
||||
}
|
||||
|
||||
bool APEv2::Header::HasFooter() const
|
||||
{
|
||||
return !(flags & FLAG_HEADER_NO_FOOTER);
|
||||
}
|
||||
|
||||
bool APEv2::Header::IsFooter() const
|
||||
{
|
||||
return !(flags & FLAG_HEADER_IS_HEADER);
|
||||
}
|
||||
|
||||
bool APEv2::Header::IsHeader() const
|
||||
{
|
||||
return !!(flags & FLAG_HEADER_IS_HEADER);
|
||||
}
|
||||
|
||||
int APEv2::Header::Encode(bytewriter_t byte_writer) const
|
||||
{
|
||||
if (bytewriter_size(byte_writer) < 32)
|
||||
return NErr_Insufficient;
|
||||
|
||||
bytewriter_write_n(byte_writer, apev2_preamble, 8);
|
||||
bytewriter_write_u32_le(byte_writer, version);
|
||||
bytewriter_write_u32_le(byte_writer, size);
|
||||
bytewriter_write_u32_le(byte_writer, items);
|
||||
bytewriter_write_u32_le(byte_writer, flags);
|
||||
bytewriter_write_zero_n(byte_writer, 8);
|
||||
|
||||
return NErr_Success;
|
||||
}
|
39
Src/replicant/nsapev2/header.h
Normal file
39
Src/replicant/nsapev2/header.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "foundation/types.h"
|
||||
#include "nu/ByteWriter.h"
|
||||
class nstest;
|
||||
|
||||
namespace APEv2
|
||||
{
|
||||
class Header
|
||||
{
|
||||
friend class ::nstest;
|
||||
public:
|
||||
Header();
|
||||
Header(const void *data);
|
||||
void SetSize(uint32_t size) { this->size = size; }
|
||||
void SetFlags(uint32_t flags) { this->flags = flags; }
|
||||
void SetItems(uint32_t items) { this->items = items; }
|
||||
bool Valid() const;
|
||||
uint32_t TagSize() const;
|
||||
bool HasHeader() const;
|
||||
bool HasFooter() const;
|
||||
bool IsFooter() const;
|
||||
bool IsHeader() const;
|
||||
int Encode(bytewriter_t byte_writer) const;
|
||||
uint32_t GetFlags() const;
|
||||
enum
|
||||
{
|
||||
SIZE=32,
|
||||
};
|
||||
private:
|
||||
uint8_t preamble[8];
|
||||
uint32_t version;
|
||||
uint32_t size;
|
||||
uint32_t items;
|
||||
uint32_t flags;
|
||||
uint64_t reserved;
|
||||
};
|
||||
}
|
||||
|
||||
|
235
Src/replicant/nsapev2/item.cpp
Normal file
235
Src/replicant/nsapev2/item.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
#include "item.h"
|
||||
#include "flags.h"
|
||||
#include "util.h"
|
||||
#include "nu/ByteWriter.h"
|
||||
#include "nu/strsafe.h"
|
||||
#include "nu/ByteReader.h"
|
||||
#include "nsapev2/nsapev2.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
http://wiki.hydrogenaudio.org/index.php?title=APE_Tag_Item
|
||||
|
||||
Item layout:
|
||||
[0-3] length of value field (little endian)
|
||||
[4-7] flags (little endian)
|
||||
[null terminated] key
|
||||
[length] value
|
||||
*/
|
||||
|
||||
APEv2::Item::Item()
|
||||
{
|
||||
len=0;
|
||||
flags=0;
|
||||
key=0;
|
||||
value=0;
|
||||
}
|
||||
|
||||
APEv2::Item::~Item()
|
||||
{
|
||||
free(key);
|
||||
free(value);
|
||||
}
|
||||
|
||||
int APEv2::Item::Read(bytereader_t byte_reader)
|
||||
{
|
||||
if (bytereader_size(byte_reader) < 8)
|
||||
return NErr_NeedMoreData;
|
||||
|
||||
/* read fixed-size fields */
|
||||
len = bytereader_read_u32_le(byte_reader);
|
||||
flags = bytereader_read_u32_le(byte_reader);
|
||||
|
||||
/* find the null terminator */
|
||||
size_t key_len = bytereader_find_zero(byte_reader);
|
||||
|
||||
/* make sure we didn't hit the end of our buffer */
|
||||
if (key_len == bytereader_size(byte_reader))
|
||||
return NErr_Insufficient;
|
||||
|
||||
/* check for empty key and also check for integer overflow */
|
||||
if (key_len == 0 || key_len+1 == 0)
|
||||
return NErr_Error;
|
||||
|
||||
key = (char *)malloc(key_len+1);
|
||||
if (key)
|
||||
{
|
||||
bytereader_read_n(byte_reader, key, key_len+1); /* read key and terminator*/
|
||||
|
||||
if (bytereader_size(byte_reader) < len) /* make sure we have room for the value! */
|
||||
{
|
||||
free(key);
|
||||
key=0;
|
||||
return NErr_NeedMoreData;
|
||||
}
|
||||
|
||||
value = (char *)malloc(len);
|
||||
if (value)
|
||||
{
|
||||
bytereader_read_n(byte_reader, value, len); /* read value */
|
||||
return NErr_Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(key);
|
||||
key=0;
|
||||
return NErr_OutOfMemory;
|
||||
}
|
||||
}
|
||||
else
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
}
|
||||
|
||||
bool APEv2::Item::IsReadOnly()
|
||||
{
|
||||
return flags & FLAG_READONLY;
|
||||
}
|
||||
|
||||
bool APEv2::Item::KeyMatch(const char *key_to_compare, int compare)
|
||||
{
|
||||
if (!key || !*key)
|
||||
return false;
|
||||
|
||||
switch (compare)
|
||||
{
|
||||
case ITEM_KEY_COMPARE_CASE_INSENSITIVE:
|
||||
#ifdef _WIN32
|
||||
return !_stricmp(key_to_compare, key);
|
||||
#else
|
||||
return !strcasecmp(key_to_compare, key);
|
||||
#endif
|
||||
case ITEM_KEY_COMPARE_CASE_SENSITIVE:
|
||||
return !strcmp(key_to_compare, key);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int APEv2::Item::Get(const void **data, size_t *datalen) const
|
||||
{
|
||||
if (!value || !len)
|
||||
return NErr_Empty;
|
||||
*data = value;
|
||||
*datalen = len;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int APEv2::Item::Set(nx_string_t string)
|
||||
{
|
||||
if (!value)
|
||||
return NErr_BadParameter;
|
||||
|
||||
flags &= ~nsapev2_item_type_mask;
|
||||
flags |= nsapev2_item_type_utf8;
|
||||
|
||||
size_t bytes;
|
||||
int ret = NXStringGetBytesSize(&bytes, string, nx_charset_utf8, 0);
|
||||
if (ret != NErr_DirectPointer && ret != NErr_Success)
|
||||
return ret;
|
||||
|
||||
void *new_value = malloc(bytes);
|
||||
if (!new_value)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
size_t bytes_copied;
|
||||
ret = NXStringGetBytes(&bytes_copied, string, new_value, bytes, nx_charset_utf8, 0);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
free(new_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
free(value);
|
||||
value=new_value;
|
||||
len=(uint32_t)bytes_copied;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int APEv2::Item::Set(const void *data, size_t datalen, int data_type)
|
||||
{
|
||||
if (!data || !datalen)
|
||||
return NErr_Error;
|
||||
|
||||
// set data type for this item
|
||||
flags &= ~nsapev2_item_type_mask;
|
||||
flags |= data_type;
|
||||
|
||||
void *new_value = realloc(value, datalen);
|
||||
if (!new_value)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
value=new_value;
|
||||
len=(uint32_t)datalen;
|
||||
memcpy(value, data, len);
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int APEv2::Item::New(size_t datalen, int data_type, void **bytes)
|
||||
{
|
||||
if (!datalen)
|
||||
return NErr_Error;
|
||||
|
||||
// set data type for this item
|
||||
flags &= ~nsapev2_item_type_mask;
|
||||
flags |= data_type;
|
||||
|
||||
void *new_value = realloc(value, datalen);
|
||||
if (!new_value)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
value=new_value;
|
||||
|
||||
len=(uint32_t)datalen;
|
||||
*bytes = value;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int APEv2::Item::SetKey(const char *tag)
|
||||
{
|
||||
if (!tag || !*tag)
|
||||
return NErr_Error;
|
||||
|
||||
char *new_key = strdup(tag);
|
||||
if (!new_key)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
free(key);
|
||||
key = new_key;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int APEv2::Item::GetKey(const char **tag) const
|
||||
{
|
||||
if (!key)
|
||||
return NErr_Error;
|
||||
*tag = key;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
size_t APEv2::Item::EncodeSize() const
|
||||
{
|
||||
return 4 /* size */ + 4 /* flags */ + strlen(key) + 1 /* NULL separator */ + len;
|
||||
}
|
||||
|
||||
uint32_t APEv2::Item::GetFlags() const
|
||||
{
|
||||
return flags;
|
||||
}
|
||||
|
||||
int APEv2::Item::Encode(bytewriter_t byte_writer) const
|
||||
{
|
||||
if (!key || !value || !len)
|
||||
return NErr_Error;
|
||||
|
||||
if (bytewriter_size(byte_writer) < EncodeSize())
|
||||
return NErr_Insufficient;
|
||||
|
||||
bytewriter_write_u32_le(byte_writer, len);
|
||||
bytewriter_write_u32_le(byte_writer, flags);
|
||||
bytewriter_write_n(byte_writer, key, strlen(key) + 1);
|
||||
bytewriter_write_n(byte_writer, value, len);
|
||||
|
||||
return NErr_Success;
|
||||
}
|
||||
|
43
Src/replicant/nsapev2/item.h
Normal file
43
Src/replicant/nsapev2/item.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
#include "foundation/types.h"
|
||||
#include "nx/nxstring.h"
|
||||
#include "nu/PtrDeque.h"
|
||||
#include "nu/ByteWriter.h"
|
||||
#include "nu/ByteReader.h"
|
||||
namespace APEv2
|
||||
{
|
||||
enum
|
||||
{
|
||||
ITEM_KEY_COMPARE_CASE_INSENSITIVE = 0,
|
||||
ITEM_KEY_COMPARE_CASE_SENSITIVE = 1,
|
||||
};
|
||||
|
||||
class Item : public nu::PtrDequeNode
|
||||
{
|
||||
public:
|
||||
Item();
|
||||
~Item();
|
||||
|
||||
/* If successful, puts incremented data pointer in new_data, and new data size remaining in new_len */
|
||||
int Read(bytereader_t byte_reader);
|
||||
|
||||
int Encode(bytewriter_t byte_writer) const;
|
||||
size_t EncodeSize() const;
|
||||
|
||||
bool IsReadOnly();
|
||||
bool KeyMatch(const char *key, int compare=ITEM_KEY_COMPARE_CASE_INSENSITIVE);
|
||||
int Get(const void **data, size_t *len) const;
|
||||
int GetKey(const char **tag) const;
|
||||
int Set(nx_string_t value);
|
||||
int Set(const void *data, size_t len, int dataType);
|
||||
int SetKey(const char *tag);
|
||||
int New(size_t datalen, int data_type, void **bytes);
|
||||
uint32_t GetFlags() const;
|
||||
|
||||
private:
|
||||
uint32_t flags;
|
||||
char *key;
|
||||
void *value;
|
||||
uint32_t len;
|
||||
};
|
||||
}
|
75
Src/replicant/nsapev2/nsapev2.h
Normal file
75
Src/replicant/nsapev2/nsapev2.h
Normal file
@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include "foundation/types.h"
|
||||
#include "nx/nxstring.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "android/nsapev2.h"
|
||||
#elif defined(_WIN32)
|
||||
#include "windows/nsapev2.h"
|
||||
#elif defined(__linux__)
|
||||
#include "linux/nsapev2.h"
|
||||
#elif defined (__APPLE__)
|
||||
#include "osx/nsapev2.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct nsapev2_header_struct_t { } *nsapev2_header_t;
|
||||
typedef struct nsapev2_tag_struct_t { } *nsapev2_tag_t;
|
||||
typedef struct nsapev2_item_struct_t { } *nsapev2_item_t;
|
||||
|
||||
// must be exactly 32 bytes
|
||||
NSAPEV2_EXPORT int NSAPEv2_Header_Valid(const void *header_data);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Header_Create(nsapev2_header_t *header, const void *header_data, size_t header_len);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Header_TagSize(const nsapev2_header_t header, uint32_t *tag_size);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Header_HasHeader(nsapev2_header_t header);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Header_Destroy(nsapev2_header_t header);
|
||||
|
||||
|
||||
// currently, this function makes a copy of any necessary data. in the future, it would be better
|
||||
// to make another version of this function that "borrows" your data
|
||||
// if you can guarantee that the memory will outlive the nsapev2_tag_t object
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_Create(nsapev2_tag_t *tag, const nsapev2_header_t header, const void *bytes, size_t bytes_len);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_New(nsapev2_tag_t *tag);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_SerializedSize(const nsapev2_tag_t tag, size_t *bytes);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_Serialize(const nsapev2_tag_t t, void *data, size_t bytes);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_Destroy(nsapev2_tag_t tag);
|
||||
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_GetFlags(nsapev2_tag_t tag, uint32_t *flags);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_SetFlags(nsapev2_tag_t tag, uint32_t flags, uint32_t mask);
|
||||
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_GetString(const nsapev2_tag_t tag, const char *key, unsigned int index, nx_string_t *value);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_SetString(nsapev2_tag_t tag, const char *key, unsigned int index, nx_string_t value);
|
||||
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_GetBinary(const nsapev2_tag_t tag, const char *key, unsigned int index, const void **bytes, size_t *length);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_SetBinary(nsapev2_tag_t tag, const char *key, unsigned int index, const void *bytes, size_t length);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_SetArtwork(nsapev2_tag_t t, const char *key, unsigned int index, const char *filename, const void *bytes, size_t length);
|
||||
/* Items */
|
||||
// flags
|
||||
static const uint32_t nsapev2_item_read_write = 0;
|
||||
static const uint32_t nsapev2_item_read_only = 1;
|
||||
|
||||
static const uint32_t nsapev2_item_type_utf8 = 0;
|
||||
static const uint32_t nsapev2_item_type_binary = 1 << 1;
|
||||
static const uint32_t nsapev2_item_type_locator = 2 << 1;
|
||||
|
||||
// mask flags with these to check the different fields
|
||||
static const uint32_t nsapev2_item_type_mask = (1 << 2) | (1 << 1);
|
||||
static const uint32_t nsapev2_item_read_mask = 1 << 0;
|
||||
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_EnumerateItems(const nsapev2_tag_t tag, const nsapev2_item_t start, nsapev2_item_t *next);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_GetItemCount(const nsapev2_tag_t t, size_t *count);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_GetItemAtIndex(const nsapev2_tag_t t, unsigned int index, nsapev2_item_t *item);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Item_GetInformation(const nsapev2_item_t item, const char **key, uint32_t *flags);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Item_GetString(const nsapev2_item_t item, nx_string_t *value);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Item_GetBinary(const nsapev2_item_t item, const void **bytes, size_t *length);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Item_SetKey(nsapev2_item_t item, const char *key);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Item_SetString(nsapev2_item_t item, nx_string_t value);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_RemoveItem(nsapev2_tag_t tag, nsapev2_item_t item);
|
||||
NSAPEV2_EXPORT int NSAPEv2_Tag_AddItem(nsapev2_tag_t tag, nsapev2_item_t *item);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
81
Src/replicant/nsapev2/nsapev2.sln
Normal file
81
Src/replicant/nsapev2/nsapev2.sln
Normal file
@ -0,0 +1,81 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29509.3
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nsapev2", "nsapev2.vcxproj", "{BF92BB16-012A-43F4-BC67-30D6D5187598}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27} = {57C90706-B25D-4ACA-9B33-95CDB2427C27}
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915} = {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D} = {E105A0A2-7391-47C5-86AC-718003524C3D}
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nu", "..\nu\nu.vcxproj", "{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nx", "..\nx\nx.vcxproj", "{57C90706-B25D-4ACA-9B33-95CDB2427C27}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jnetlib", "..\jnetlib\jnetlib.vcxproj", "{E105A0A2-7391-47C5-86AC-718003524C3D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\zlib\zlib.vcxproj", "{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{BF92BB16-012A-43F4-BC67-30D6D5187598}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{BF92BB16-012A-43F4-BC67-30D6D5187598}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{BF92BB16-012A-43F4-BC67-30D6D5187598}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{BF92BB16-012A-43F4-BC67-30D6D5187598}.Debug|x64.Build.0 = Debug|x64
|
||||
{BF92BB16-012A-43F4-BC67-30D6D5187598}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{BF92BB16-012A-43F4-BC67-30D6D5187598}.Release|Win32.Build.0 = Release|Win32
|
||||
{BF92BB16-012A-43F4-BC67-30D6D5187598}.Release|x64.ActiveCfg = Release|x64
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.Build.0 = Release|Win32
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.ActiveCfg = Release|x64
|
||||
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.Build.0 = Release|x64
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|x64.Build.0 = Debug|x64
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|Win32.Build.0 = Release|Win32
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|x64.ActiveCfg = Release|x64
|
||||
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|x64.Build.0 = Release|x64
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.Build.0 = Debug|x64
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.Build.0 = Release|Win32
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.ActiveCfg = Release|x64
|
||||
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.Build.0 = Release|x64
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.Build.0 = Debug|x64
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.Build.0 = Release|Win32
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.ActiveCfg = Release|x64
|
||||
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C4E799C1-027B-487B-8E1A-31F2D26A1AFE}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
172
Src/replicant/nsapev2/nsapev2.vcxproj
Normal file
172
Src/replicant/nsapev2/nsapev2.vcxproj
Normal file
@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{BF92BB16-012A-43F4-BC67-30D6D5187598}</ProjectGuid>
|
||||
<RootNamespace>nsapev2</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>x86_Debug\</OutDir>
|
||||
<IntDir>x86_Debug\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>x64_Debug\</OutDir>
|
||||
<IntDir>x64_Debug\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>x86_Release\</OutDir>
|
||||
<IntDir>x86_Release\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>x64_Release\</OutDir>
|
||||
<IntDir>x64_Release\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(ProjectDir)x86_Debug\$(ProjectName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(ProjectDir)x64_Debug\$(ProjectName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(ProjectDir)x86_Release\$(ProjectName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN64;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(ProjectDir)x64_Release\$(ProjectName).lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="header.cpp" />
|
||||
<ClCompile Include="item.cpp" />
|
||||
<ClCompile Include="nsapev2_common.cpp" />
|
||||
<ClCompile Include="tag.cpp" />
|
||||
<ClCompile Include="windows\nsapev2.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="flags.h" />
|
||||
<ClInclude Include="header.h" />
|
||||
<ClInclude Include="item.h" />
|
||||
<ClInclude Include="nsapev2.h" />
|
||||
<ClInclude Include="precomp.h" />
|
||||
<ClInclude Include="tag.h" />
|
||||
<ClInclude Include="util.h" />
|
||||
<ClInclude Include="windows\nsapev2.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
465
Src/replicant/nsapev2/nsapev2_common.cpp
Normal file
465
Src/replicant/nsapev2/nsapev2_common.cpp
Normal file
@ -0,0 +1,465 @@
|
||||
#include "nsapev2.h"
|
||||
#include "nsapev2/header.h"
|
||||
#include "nsapev2/tag.h"
|
||||
#include <new>
|
||||
|
||||
int NSAPEv2_Header_Valid(const void *header_data)
|
||||
|
||||
{
|
||||
if (APEv2::Header(header_data).Valid())
|
||||
return NErr_Success;
|
||||
else
|
||||
return NErr_False;
|
||||
}
|
||||
|
||||
int NSAPEv2_Header_Create(nsapev2_header_t *header, const void *header_data, size_t header_len)
|
||||
{
|
||||
if (header_len < 10 || NSAPEv2_Header_Valid(header_data) != NErr_Success)
|
||||
return NErr_Error;
|
||||
|
||||
nsapev2_header_t new_header = (nsapev2_header_t)new (std::nothrow) APEv2::Header(header_data);
|
||||
if (!new_header)
|
||||
return NErr_OutOfMemory;
|
||||
*header = new_header;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int NSAPEv2_Header_TagSize(const nsapev2_header_t h, uint32_t *tag_size)
|
||||
{
|
||||
const APEv2::Header *header = (const APEv2::Header *)h;
|
||||
if (!header)
|
||||
return NErr_NullPointer;
|
||||
|
||||
*tag_size = header->TagSize();
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int NSAPEv2_Header_HasHeader(nsapev2_header_t h)
|
||||
{
|
||||
const APEv2::Header *header = (const APEv2::Header *)h;
|
||||
if (!header)
|
||||
return NErr_NullPointer;
|
||||
|
||||
if (header->HasHeader())
|
||||
return NErr_Success;
|
||||
else
|
||||
return NErr_False;
|
||||
}
|
||||
|
||||
int NSAPEv2_Header_Destroy(nsapev2_header_t h)
|
||||
{
|
||||
const APEv2::Header *header = (const APEv2::Header *)h;
|
||||
if (!header)
|
||||
return NErr_NullPointer;
|
||||
|
||||
delete header;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_Create(nsapev2_tag_t *t, const nsapev2_header_t h, const void *bytes, size_t bytes_len)
|
||||
{
|
||||
const APEv2::Header *header = (const APEv2::Header *)h;
|
||||
if (!header)
|
||||
return NErr_NullPointer;
|
||||
|
||||
APEv2::Tag *tag = new (std::nothrow) APEv2::Tag;
|
||||
if (!tag)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
int ret = tag->Parse(header, bytes, bytes_len);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
delete tag;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*t = (nsapev2_tag_t)tag;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_New(nsapev2_tag_t *t)
|
||||
{
|
||||
APEv2::Header *new_header = new (std::nothrow) APEv2::Header();
|
||||
if (!new_header)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
APEv2::Tag *tag = new (std::nothrow) APEv2::Tag;
|
||||
if (!tag)
|
||||
{
|
||||
delete new_header;
|
||||
return NErr_OutOfMemory;
|
||||
}
|
||||
|
||||
*t = (nsapev2_tag_t)tag;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_SerializedSize(const nsapev2_tag_t t, size_t *bytes)
|
||||
{
|
||||
const APEv2::Tag *tag = (const APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_BadParameter;
|
||||
|
||||
*bytes = tag->EncodeSize();
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_Serialize(const nsapev2_tag_t t, void *data, size_t bytes)
|
||||
{
|
||||
const APEv2::Tag *tag = (const APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_BadParameter;
|
||||
|
||||
return tag->Encode(data, bytes);
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_Destroy(nsapev2_tag_t t)
|
||||
{
|
||||
APEv2::Tag *tag = (APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_NullPointer;
|
||||
delete tag;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_GetFlags(nsapev2_tag_t t, uint32_t *flags)
|
||||
{
|
||||
APEv2::Tag *tag = (APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_BadParameter;
|
||||
|
||||
return tag->GetFlags(flags);
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_SetFlags(nsapev2_tag_t t, uint32_t flags, uint32_t mask)
|
||||
{
|
||||
APEv2::Tag *tag = (APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_BadParameter;
|
||||
|
||||
return tag->SetFlags(flags, mask);
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_GetString(const nsapev2_tag_t t, const char *key, unsigned int index, nx_string_t *value)
|
||||
{
|
||||
const APEv2::Tag *tag = (const APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_Empty;
|
||||
|
||||
const void *data;
|
||||
size_t data_len;
|
||||
int ret = tag->GetData(key, index, &data, &data_len);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
|
||||
return NXStringCreateWithBytes(value, data, data_len, nx_charset_utf8);
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_SetString(nsapev2_tag_t t, const char *key, unsigned int index, nx_string_t value)
|
||||
{
|
||||
APEv2::Tag *tag = (APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_BadParameter;
|
||||
|
||||
if (value)
|
||||
{
|
||||
APEv2::Item *item;
|
||||
int ret = tag->GetItem(key, index, &item);
|
||||
if (ret == NErr_Success)
|
||||
{
|
||||
return item->Set(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no such item, need to make a new one */
|
||||
item = new (std::nothrow) APEv2::Item;
|
||||
if (!item)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
ret = item->SetKey(key);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
delete item;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = item->Set(value);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
delete item;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tag->AddItem(item);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
delete item;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NErr_Success;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tag->Remove(key, index);
|
||||
return NErr_Success;
|
||||
}
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_GetBinary(const nsapev2_tag_t t, const char *key, unsigned int index, const void **bytes, size_t *length)
|
||||
{
|
||||
const APEv2::Tag *tag = (const APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_Empty;
|
||||
|
||||
return tag->GetData(key, index, bytes, length);
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_SetBinary(nsapev2_tag_t t, const char *key, unsigned int index, const void *bytes, size_t length)
|
||||
{
|
||||
APEv2::Tag *tag = (APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_BadParameter;
|
||||
|
||||
if (bytes)
|
||||
{
|
||||
APEv2::Item *item;
|
||||
int ret = tag->GetItem(key, index, &item);
|
||||
if (ret == NErr_Success)
|
||||
{
|
||||
return item->Set(bytes, length, nsapev2_item_type_binary);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no such item, need to make a new one */
|
||||
item = new (std::nothrow) APEv2::Item;
|
||||
if (!item)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
ret = item->SetKey(key);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
delete item;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = item->Set(bytes, length, nsapev2_item_type_binary);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
delete item;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tag->AddItem(item);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
delete item;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NErr_Success;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tag->Remove(key, index);
|
||||
return NErr_Success;
|
||||
}
|
||||
}
|
||||
|
||||
static int SetArtwork(APEv2::Item *item, const char *filename, const void *bytes, size_t length)
|
||||
{
|
||||
|
||||
size_t filename_length = filename?strlen(filename):0;
|
||||
size_t total_length = filename_length
|
||||
+ 1 /* null separator */
|
||||
+ length;
|
||||
|
||||
void *item_data;
|
||||
int ret = item->New(total_length, nsapev2_item_type_binary, &item_data);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
|
||||
bytewriter_s byte_writer;
|
||||
bytewriter_init(&byte_writer, item_data, total_length);
|
||||
bytewriter_write_n(&byte_writer, filename, filename_length);
|
||||
bytewriter_write_u8(&byte_writer, 0);
|
||||
bytewriter_write_n(&byte_writer, bytes, length);
|
||||
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_SetArtwork(nsapev2_tag_t t, const char *key, unsigned int index, const char *filename, const void *bytes, size_t length)
|
||||
{
|
||||
APEv2::Tag *tag = (APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_BadParameter;
|
||||
|
||||
if (bytes)
|
||||
{
|
||||
|
||||
APEv2::Item *item;
|
||||
int ret = tag->GetItem(key, index, &item);
|
||||
if (ret == NErr_Success)
|
||||
{
|
||||
return SetArtwork(item, filename, bytes, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no such item, need to make a new one */
|
||||
item = new (std::nothrow) APEv2::Item;
|
||||
if (!item)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
ret = item->SetKey(key);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
delete item;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = SetArtwork(item, filename, bytes, length);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
delete item;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tag->AddItem(item);
|
||||
if (ret != NErr_Success)
|
||||
{
|
||||
delete item;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NErr_Success;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tag->Remove(key, index);
|
||||
return NErr_Success;
|
||||
}
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_EnumerateItems(const nsapev2_tag_t t, const nsapev2_item_t s, nsapev2_item_t *next)
|
||||
{
|
||||
const APEv2::Tag *tag = (const APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_NullPointer;
|
||||
|
||||
const APEv2::Item *start = (const APEv2::Item *)s;
|
||||
return tag->EnumerateItems(start, (APEv2::Item **)next);
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_GetItemCount(const nsapev2_tag_t t, size_t *count)
|
||||
{
|
||||
const APEv2::Tag *tag = (const APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_NullPointer;
|
||||
|
||||
return tag->GetItemCount(count);
|
||||
}
|
||||
|
||||
|
||||
int NSAPEv2_Tag_GetItemAtIndex(const nsapev2_tag_t t, unsigned int index, nsapev2_item_t *item)
|
||||
{
|
||||
APEv2::Tag *tag = (APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_NullPointer;
|
||||
|
||||
return tag->GetItemAtIndex(index, (APEv2::Item **)item);
|
||||
}
|
||||
|
||||
int NSAPEv2_Item_GetInformation(const nsapev2_item_t i, const char **key, uint32_t *flags)
|
||||
{
|
||||
const APEv2::Item *item = (const APEv2::Item *)i;
|
||||
if (!item)
|
||||
return NErr_NullPointer;
|
||||
|
||||
if (key)
|
||||
{
|
||||
int ret = item->GetKey(key);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (flags)
|
||||
*flags = item->GetFlags();
|
||||
return NErr_Success;
|
||||
|
||||
}
|
||||
|
||||
int NSAPEv2_Item_GetString(const nsapev2_item_t i, nx_string_t *value)
|
||||
{
|
||||
const APEv2::Item *item = (const APEv2::Item *)i;
|
||||
if (!item)
|
||||
return NErr_BadParameter;
|
||||
|
||||
const void *data;
|
||||
size_t data_len;
|
||||
int ret = item->Get(&data, &data_len);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
|
||||
return NXStringCreateWithBytes(value, data, data_len, nx_charset_utf8);
|
||||
}
|
||||
|
||||
int NSAPEv2_Item_GetBinary(const nsapev2_item_t i, const void **bytes, size_t *length)
|
||||
{
|
||||
const APEv2::Item *item = (const APEv2::Item *)i;
|
||||
if (!item)
|
||||
return NErr_BadParameter;
|
||||
|
||||
return item->Get(bytes, length);
|
||||
}
|
||||
|
||||
int NSAPEv2_Item_SetKey(nsapev2_item_t i, const char *key)
|
||||
{
|
||||
APEv2::Item *item = (APEv2::Item *)i;
|
||||
if (!item)
|
||||
return NErr_BadParameter;
|
||||
|
||||
return item->SetKey(key);
|
||||
}
|
||||
|
||||
int NSAPEv2_Item_SetString(nsapev2_item_t i, nx_string_t value)
|
||||
{
|
||||
APEv2::Item *item = (APEv2::Item *)i;
|
||||
if (!item)
|
||||
return NErr_BadParameter;
|
||||
|
||||
return item->Set(value);
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_RemoveItem(nsapev2_tag_t t, nsapev2_item_t i)
|
||||
{
|
||||
APEv2::Tag *tag = (APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_BadParameter;
|
||||
|
||||
APEv2::Item *item = (APEv2::Item *)i;
|
||||
if (!item)
|
||||
return NErr_BadParameter;
|
||||
|
||||
tag->RemoveItem(item);
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int NSAPEv2_Tag_AddItem(nsapev2_tag_t t, nsapev2_item_t *i)
|
||||
{
|
||||
APEv2::Tag *tag = (APEv2::Tag *)t;
|
||||
if (!tag)
|
||||
return NErr_BadParameter;
|
||||
|
||||
APEv2::Item **item = (APEv2::Item **)i;
|
||||
if (!item)
|
||||
return NErr_NullPointer;
|
||||
|
||||
*item = new (std::nothrow) APEv2::Item;
|
||||
if (!*item)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
return tag->AddItem(*item);
|
||||
}
|
26
Src/replicant/nsapev2/precomp.h
Normal file
26
Src/replicant/nsapev2/precomp.h
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// precomp.h
|
||||
// nsapev2
|
||||
//
|
||||
|
||||
#include "foundation/error.h"
|
||||
#include "foundation/types.h"
|
||||
|
||||
#include "nu/ByteReader.h"
|
||||
#include "nu/ByteWriter.h"
|
||||
#include "nu/strsafe.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "nu/PtrDeque.h"
|
||||
#endif
|
||||
|
||||
#include "nx/nxstring.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "header.h"
|
||||
#include "new"
|
||||
#endif
|
285
Src/replicant/nsapev2/tag.cpp
Normal file
285
Src/replicant/nsapev2/tag.cpp
Normal file
@ -0,0 +1,285 @@
|
||||
#include "tag.h"
|
||||
#include "header.h"
|
||||
#include "flags.h"
|
||||
#ifdef _WIN32
|
||||
#include "../nu/ns_wc.h"
|
||||
#include "nu/strsafe.h"
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
#include <new>
|
||||
#include "nu/ByteWriter.h"
|
||||
|
||||
/*
|
||||
http://wiki.hydrogenaudio.org/index.php?title=APEv2_specification
|
||||
*/
|
||||
|
||||
APEv2::Tag::Tag()
|
||||
{
|
||||
flags = 0; // default to writing just a footer
|
||||
}
|
||||
|
||||
APEv2::Tag::~Tag()
|
||||
{
|
||||
items.deleteAll();
|
||||
}
|
||||
|
||||
/* Parsing */
|
||||
int APEv2::Tag::Parse(const APEv2::Header *header, const void *_data, size_t len)
|
||||
{
|
||||
flags = header->GetFlags();
|
||||
|
||||
if (header->IsFooter())
|
||||
{
|
||||
flags &= ~FLAG_HEADER_NO_FOOTER; // winamp 5.54 had this flag reversed, so let's correct it
|
||||
if (header->HasHeader())
|
||||
{
|
||||
// TODO: validate header
|
||||
_data = (const uint8_t *)_data + 32;
|
||||
len -= 32;
|
||||
}
|
||||
len -= 32; /* footer is counted in the size */
|
||||
return ParseData(_data, len);
|
||||
}
|
||||
else /* IsHeader() */
|
||||
{
|
||||
if (header->HasFooter())
|
||||
{
|
||||
// TODO: validate footer
|
||||
len -= 32;
|
||||
}
|
||||
return ParseData(_data, len);
|
||||
}
|
||||
}
|
||||
|
||||
int APEv2::Tag::ParseData(const void *data, size_t len)
|
||||
{
|
||||
bytereader_s byte_reader;
|
||||
bytereader_init(&byte_reader, data, len);
|
||||
|
||||
while (bytereader_size(&byte_reader))
|
||||
{
|
||||
Item *item = new (std::nothrow) Item;
|
||||
if (!item)
|
||||
return NErr_OutOfMemory;
|
||||
|
||||
int ret = item->Read(&byte_reader);
|
||||
if (ret == NErr_Success)
|
||||
{
|
||||
items.push_back(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete item;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
/* Retrieving Data */
|
||||
int APEv2::Tag::GetItem(const char *key, unsigned int index, Item **item, int compare) const
|
||||
{
|
||||
unsigned int i=0;
|
||||
for (ItemList::iterator itr=items.begin();itr!=items.end();itr++)
|
||||
{
|
||||
/* check if it's a string first, and then match the key next (will be faster) */
|
||||
if (itr->KeyMatch(key, compare))
|
||||
{
|
||||
if (i++ < index)
|
||||
continue;
|
||||
|
||||
*item = *itr;
|
||||
return NErr_Success;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > index) /* if we found the key once, but the index was too high */
|
||||
return NErr_EndOfEnumeration;
|
||||
return NErr_Empty;
|
||||
}
|
||||
|
||||
int APEv2::Tag::GetItemAtIndex(unsigned int index, Item **item) const
|
||||
{
|
||||
unsigned int i=0;
|
||||
for (ItemList::iterator itr=items.begin();itr!=items.end();itr++)
|
||||
{
|
||||
if (i++ < index)
|
||||
continue;
|
||||
|
||||
*item = *itr;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
return NErr_EndOfEnumeration;
|
||||
}
|
||||
|
||||
int APEv2::Tag::GetData(const char *key, unsigned int index, const void **data, size_t *data_len, int compare) const
|
||||
{
|
||||
Item *item=0;
|
||||
int ret = GetItem(key, index, &item, compare);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
|
||||
return item->Get(data, data_len);
|
||||
}
|
||||
|
||||
int APEv2::Tag::EnumerateItems(const Item *start, Item **item) const
|
||||
{
|
||||
Item *next_item = 0;
|
||||
if (!start)
|
||||
{
|
||||
next_item = items.front();
|
||||
}
|
||||
else
|
||||
{
|
||||
next_item = static_cast<APEv2::Item *>(start->next);
|
||||
}
|
||||
*item = next_item;
|
||||
if (next_item)
|
||||
return NErr_Success;
|
||||
else if (start)
|
||||
return NErr_EndOfEnumeration;
|
||||
else
|
||||
return NErr_Empty;
|
||||
}
|
||||
|
||||
int APEv2::Tag::FindItemByKey(const char *key, Item **item, int compare) const
|
||||
{
|
||||
for (ItemList::iterator itr=items.begin();itr!=items.end();itr++)
|
||||
{
|
||||
if (itr->KeyMatch(key, compare))
|
||||
{
|
||||
*item = *itr;
|
||||
return NErr_Success;
|
||||
}
|
||||
}
|
||||
return NErr_Unknown;
|
||||
}
|
||||
|
||||
bool APEv2::Tag::IsReadOnly() const
|
||||
{
|
||||
return flags & FLAG_READONLY;
|
||||
}
|
||||
|
||||
int APEv2::Tag::GetItemCount(size_t *count) const
|
||||
{
|
||||
*count = items.size();
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int APEv2::Tag::GetFlags(uint32_t *flags) const
|
||||
{
|
||||
*flags = this->flags;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
/* Setting Data */
|
||||
int APEv2::Tag::AddItem(APEv2::Item *new_item)
|
||||
{
|
||||
items.push_back(new_item);
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
int APEv2::Tag::SetFlags(uint32_t newflags, uint32_t mask)
|
||||
{
|
||||
flags = (flags & ~mask) | newflags;
|
||||
return NErr_Success;
|
||||
}
|
||||
|
||||
/* Removing Data */
|
||||
void APEv2::Tag::Clear()
|
||||
{
|
||||
items.deleteAll();
|
||||
}
|
||||
|
||||
void APEv2::Tag::Remove(const char *key, unsigned int starting_index, int compare)
|
||||
{
|
||||
for (ItemList::iterator itr=items.begin();itr!=items.end();)
|
||||
{
|
||||
ItemList::iterator next = itr;
|
||||
next++;
|
||||
APEv2::Item *item = *itr;
|
||||
|
||||
if (item->KeyMatch(key, compare))
|
||||
{
|
||||
if (starting_index)
|
||||
{
|
||||
starting_index--;
|
||||
}
|
||||
else
|
||||
{
|
||||
items.erase(item);
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
itr=next;
|
||||
}
|
||||
}
|
||||
|
||||
void APEv2::Tag::RemoveItem(Item *item)
|
||||
{
|
||||
items.erase(item);
|
||||
delete item;
|
||||
}
|
||||
|
||||
/* Serializing */
|
||||
size_t APEv2::Tag::EncodeSize() const
|
||||
{
|
||||
size_t total_size=0;
|
||||
|
||||
if (flags & FLAG_HEADER_HAS_HEADER)
|
||||
total_size+=Header::SIZE;
|
||||
|
||||
for (ItemList::iterator itr=items.begin();itr!=items.end();itr++)
|
||||
{
|
||||
total_size += itr->EncodeSize();
|
||||
}
|
||||
|
||||
if (!(flags & FLAG_HEADER_NO_FOOTER))
|
||||
total_size+=Header::SIZE;
|
||||
|
||||
return total_size;
|
||||
}
|
||||
|
||||
int APEv2::Tag::Encode(void *data, size_t len) const
|
||||
{
|
||||
bytewriter_s byte_writer;
|
||||
bytewriter_init(&byte_writer, data, len);
|
||||
|
||||
if (flags & FLAG_HEADER_HAS_HEADER)
|
||||
{
|
||||
Header header;
|
||||
header.SetSize((uint32_t)len - Header::SIZE);
|
||||
header.SetItems((uint32_t)items.size());
|
||||
header.SetFlags((flags & FLAG_HEADER_ENCODE_MASK)|FLAG_HEADER_IS_HEADER);
|
||||
|
||||
int ret = header.Encode(&byte_writer);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (ItemList::iterator itr=items.begin();itr!=items.end();itr++)
|
||||
{
|
||||
int ret = itr->Encode(&byte_writer);
|
||||
if (ret!= NErr_Success)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!(flags & FLAG_HEADER_NO_FOOTER))
|
||||
{
|
||||
Header footer;
|
||||
|
||||
if (flags & FLAG_HEADER_HAS_HEADER)
|
||||
footer.SetSize((uint32_t)len - Header::SIZE);
|
||||
else
|
||||
footer.SetSize((uint32_t)len);
|
||||
footer.SetItems((uint32_t)items.size());
|
||||
footer.SetFlags((flags & FLAG_HEADER_ENCODE_MASK));
|
||||
|
||||
int ret = footer.Encode(&byte_writer);
|
||||
if (ret != NErr_Success)
|
||||
return ret;
|
||||
}
|
||||
return NErr_Success;
|
||||
}
|
50
Src/replicant/nsapev2/tag.h
Normal file
50
Src/replicant/nsapev2/tag.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#include "foundation/types.h"
|
||||
#include "nu/PtrDeque.h"
|
||||
#include "item.h"
|
||||
#include "flags.h"
|
||||
#include "header.h"
|
||||
|
||||
namespace APEv2
|
||||
{
|
||||
class Tag
|
||||
{
|
||||
public:
|
||||
Tag();
|
||||
~Tag();
|
||||
|
||||
/* Parsing */
|
||||
int Parse(const APEv2::Header *header, const void *data, size_t len);
|
||||
|
||||
/* Retrieving Data */
|
||||
int GetItem(const char *key, unsigned int index, Item **item, int compare=ITEM_KEY_COMPARE_CASE_INSENSITIVE) const;
|
||||
int GetItemAtIndex(unsigned int index, Item **) const;
|
||||
int GetData(const char *tag, unsigned int index, const void **data, size_t *data_len, int compare=ITEM_KEY_COMPARE_CASE_INSENSITIVE) const;
|
||||
int EnumerateItems(const Item *start, Item **item) const;
|
||||
int FindItemByKey(const char *key, Item **item, int compare=ITEM_KEY_COMPARE_CASE_INSENSITIVE) const;
|
||||
bool IsReadOnly() const;
|
||||
int GetItemCount(size_t *count) const;
|
||||
int GetFlags(uint32_t *flags) const;
|
||||
|
||||
/* Setting Data */
|
||||
int AddItem(APEv2::Item *new_item);
|
||||
int SetFlags(uint32_t flags, uint32_t mask);
|
||||
|
||||
/* Removing Data */
|
||||
void Clear();
|
||||
void Remove(const char *key, unsigned int starting_index, int compare=ITEM_KEY_COMPARE_CASE_INSENSITIVE); // removes all items matching a key, but skips the first 'starting_index' items
|
||||
void RemoveItem(Item *item);
|
||||
/* Serializing */
|
||||
size_t EncodeSize() const;
|
||||
int Encode(void *data, size_t len) const;
|
||||
|
||||
private: /* methods */
|
||||
int ParseData(const void *data, size_t len); /* helper function, call with data pointing to beginning of items block (skip header), and length without footer. */
|
||||
|
||||
private: /* data */
|
||||
typedef nu::PtrDeque<Item> ItemList;
|
||||
ItemList items;
|
||||
uint32_t flags;
|
||||
};
|
||||
}
|
||||
|
1
Src/replicant/nsapev2/util.h
Normal file
1
Src/replicant/nsapev2/util.h
Normal file
@ -0,0 +1 @@
|
||||
#pragma once
|
1
Src/replicant/nsapev2/windows/nsapev2.cpp
Normal file
1
Src/replicant/nsapev2/windows/nsapev2.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "nsapev2/nsapev2.h"
|
20
Src/replicant/nsapev2/windows/nsapev2.h
Normal file
20
Src/replicant/nsapev2/windows/nsapev2.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "foundation/export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
#ifdef NSID3V2_EXPORTS
|
||||
#define NSAPEV2_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define NSAPEV2_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
*/
|
||||
#define NSAPEV2_EXPORT
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user