123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #include "item.h"
- #include "flags.h"
- #include "util.h"
- #include <strsafe.h>
- #include <stdint.h>
- /*
- http://wiki.hydrogenaudio.org/index.php?title=APE_Tag_Item
- */
- APEv2::Item::Item()
- {
- refCount=1;
- len=0;
- flags=0;
- key=0;
- value=0;
- }
- APEv2::Item::~Item()
- {
- free(key);
- free(value);
- }
- void APEv2::Item::Retain()
- {
- refCount++;
- }
- void APEv2::Item::Release()
- {
- if (--refCount == 0)
- delete this;
- }
- int APEv2::Item::Read(void *_data, size_t datalen, void **new_data, size_t *new_len)
- {
- char *data = (char *)_data;
- if (datalen < 4)
- return APEV2_TOO_SMALL;
- memcpy(&len, data, 4);
- len = ATON32(len);
- data+=4;
- datalen-=4;
- if (datalen < 4)
- return APEV2_TOO_SMALL;
- memcpy(&flags, data, 4);
- flags = ATON32(flags);
- data+=4;
- datalen-=4;
- uint32_t key_len=0;
- for (uint32_t i=0;i<datalen;i++)
- {
- if (data[i] == 0)
- {
- key_len=i;
- break;
- }
- }
- if (key_len == datalen)
- return APEV2_TOO_SMALL;
- if (key_len == 0)
- return APEV2_FAILURE;
- if (key)
- {
- free(key);
- key = 0;
- }
- key = (char *)calloc(key_len+1, sizeof(char));
- if (key)
- {
- StringCchCopyA(key, key_len+1, data);
- datalen-=(key_len+1);
- data+=(key_len+1);
- if (datalen < len)
- {
- free(key);
- key = 0;
- return APEV2_TOO_SMALL;
- }
- if (value)
- {
- free(value);
- value = 0;
- }
- value = (char *)calloc(len, sizeof(char));
- if (value)
- {
- memcpy(value, data, len);
- datalen-=len;
- data+=len;
- *new_len = datalen;
- *new_data=data;
- return APEV2_SUCCESS;
- }
- else
- {
- free(key);
- return APEV2_FAILURE;
- }
- }
- else
- return APEV2_FAILURE;
- }
- bool APEv2::Item::IsReadOnly()
- {
- return flags & FLAG_READONLY;
- }
- bool APEv2::Item::IsString()
- {
- return (flags & MASK_ITEM_TYPE) == FLAG_ITEM_TEXT;
- }
- bool APEv2::Item::KeyMatch(const char *key_to_compare, int compare)
- {
- if (!key || !*key)
- return false;
- switch (compare)
- {
- case ITEM_KEY_COMPARE_CASE_INSENSITIVE:
- return !_stricmp(key_to_compare, key);
- case ITEM_KEY_COMPARE_CASE_SENSITIVE:
- return !strcmp(key_to_compare, key);
- default:
- return false;
- }
- }
- int APEv2::Item::Get(void **data, size_t *datalen)
- {
- if (!value || !len)
- return APEV2_FAILURE;
- *data = value;
- *datalen = len;
- return APEV2_SUCCESS;
- }
- int APEv2::Item::Set(const void *data, size_t datalen, int dataType)
- {
- if (!data || !datalen)
- return APEV2_FAILURE;
- // set data type for this item
- flags &= ~MASK_ITEM_TYPE;
- flags |= dataType;
- free(value);
- value = malloc(datalen);
- len=(uint32_t)datalen;
- memcpy(value, data, len);
- return APEV2_SUCCESS;
- }
- int APEv2::Item::SetKey(const char *tag)
- {
- if (!tag || !*tag)
- return APEV2_FAILURE;
- free(key);
- key = _strdup(tag);
- return APEV2_SUCCESS;
- }
- int APEv2::Item::GetKey(const char **tag)
- {
- if (!key)
- return APEV2_FAILURE;
- *tag = key;
- return APEV2_SUCCESS;
- }
- size_t APEv2::Item::EncodeSize()
- {
- return 4 /* size */ + 4 /* flags */ + (key && *key ? strlen(key) : 0) + 1 /* NULL separator */ + len;
- }
- int APEv2::Item::Encode(void *data, size_t datalen)
- {
- if (!key || !value || !len)
- return APEV2_FAILURE;
- if (datalen < EncodeSize())
- return APEV2_TOO_SMALL;
- int8_t *ptr = (int8_t *)data;
- // write data length
- int32_t _len = NTOA32(len);
- memcpy(ptr, &_len, sizeof(_len));
- ptr+=sizeof(_len);
- datalen-=sizeof(_len);
- // write flags
- int32_t _flags = NTOA32(flags);
- memcpy(ptr, &_flags, sizeof(_flags));
- ptr+=sizeof(_flags);
- datalen-=sizeof(_flags);
- // write key and null terminator
- if (StringCchCopyExA((char *)ptr, datalen, key, (char **) &ptr, &datalen, 0) != S_OK)
- return APEV2_FAILURE;
- // account for null separator
- ptr++;
- datalen--;
- // write data
- memcpy(ptr, value, len);
- return APEV2_SUCCESS;
- }
|