tag.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. #include "tag.h"
  2. #include "header.h"
  3. #include "flags.h"
  4. #ifdef _WIN32
  5. #include "../nu/ns_wc.h"
  6. #include "nu/strsafe.h"
  7. #endif
  8. #include <limits.h>
  9. #include <new>
  10. #include "nu/ByteWriter.h"
  11. /*
  12. http://wiki.hydrogenaudio.org/index.php?title=APEv2_specification
  13. */
  14. APEv2::Tag::Tag()
  15. {
  16. flags = 0; // default to writing just a footer
  17. }
  18. APEv2::Tag::~Tag()
  19. {
  20. items.deleteAll();
  21. }
  22. /* Parsing */
  23. int APEv2::Tag::Parse(const APEv2::Header *header, const void *_data, size_t len)
  24. {
  25. flags = header->GetFlags();
  26. if (header->IsFooter())
  27. {
  28. flags &= ~FLAG_HEADER_NO_FOOTER; // winamp 5.54 had this flag reversed, so let's correct it
  29. if (header->HasHeader())
  30. {
  31. // TODO: validate header
  32. _data = (const uint8_t *)_data + 32;
  33. len -= 32;
  34. }
  35. len -= 32; /* footer is counted in the size */
  36. return ParseData(_data, len);
  37. }
  38. else /* IsHeader() */
  39. {
  40. if (header->HasFooter())
  41. {
  42. // TODO: validate footer
  43. len -= 32;
  44. }
  45. return ParseData(_data, len);
  46. }
  47. }
  48. int APEv2::Tag::ParseData(const void *data, size_t len)
  49. {
  50. bytereader_s byte_reader;
  51. bytereader_init(&byte_reader, data, len);
  52. while (bytereader_size(&byte_reader))
  53. {
  54. Item *item = new (std::nothrow) Item;
  55. if (!item)
  56. return NErr_OutOfMemory;
  57. int ret = item->Read(&byte_reader);
  58. if (ret == NErr_Success)
  59. {
  60. items.push_back(item);
  61. }
  62. else
  63. {
  64. delete item;
  65. return ret;
  66. }
  67. }
  68. return NErr_Success;
  69. }
  70. /* Retrieving Data */
  71. int APEv2::Tag::GetItem(const char *key, unsigned int index, Item **item, int compare) const
  72. {
  73. unsigned int i=0;
  74. for (ItemList::iterator itr=items.begin();itr!=items.end();itr++)
  75. {
  76. /* check if it's a string first, and then match the key next (will be faster) */
  77. if (itr->KeyMatch(key, compare))
  78. {
  79. if (i++ < index)
  80. continue;
  81. *item = *itr;
  82. return NErr_Success;
  83. }
  84. }
  85. if (i > index) /* if we found the key once, but the index was too high */
  86. return NErr_EndOfEnumeration;
  87. return NErr_Empty;
  88. }
  89. int APEv2::Tag::GetItemAtIndex(unsigned int index, Item **item) const
  90. {
  91. unsigned int i=0;
  92. for (ItemList::iterator itr=items.begin();itr!=items.end();itr++)
  93. {
  94. if (i++ < index)
  95. continue;
  96. *item = *itr;
  97. return NErr_Success;
  98. }
  99. return NErr_EndOfEnumeration;
  100. }
  101. int APEv2::Tag::GetData(const char *key, unsigned int index, const void **data, size_t *data_len, int compare) const
  102. {
  103. Item *item=0;
  104. int ret = GetItem(key, index, &item, compare);
  105. if (ret != NErr_Success)
  106. return ret;
  107. return item->Get(data, data_len);
  108. }
  109. int APEv2::Tag::EnumerateItems(const Item *start, Item **item) const
  110. {
  111. Item *next_item = 0;
  112. if (!start)
  113. {
  114. next_item = items.front();
  115. }
  116. else
  117. {
  118. next_item = static_cast<APEv2::Item *>(start->next);
  119. }
  120. *item = next_item;
  121. if (next_item)
  122. return NErr_Success;
  123. else if (start)
  124. return NErr_EndOfEnumeration;
  125. else
  126. return NErr_Empty;
  127. }
  128. int APEv2::Tag::FindItemByKey(const char *key, Item **item, int compare) const
  129. {
  130. for (ItemList::iterator itr=items.begin();itr!=items.end();itr++)
  131. {
  132. if (itr->KeyMatch(key, compare))
  133. {
  134. *item = *itr;
  135. return NErr_Success;
  136. }
  137. }
  138. return NErr_Unknown;
  139. }
  140. bool APEv2::Tag::IsReadOnly() const
  141. {
  142. return flags & FLAG_READONLY;
  143. }
  144. int APEv2::Tag::GetItemCount(size_t *count) const
  145. {
  146. *count = items.size();
  147. return NErr_Success;
  148. }
  149. int APEv2::Tag::GetFlags(uint32_t *flags) const
  150. {
  151. *flags = this->flags;
  152. return NErr_Success;
  153. }
  154. /* Setting Data */
  155. int APEv2::Tag::AddItem(APEv2::Item *new_item)
  156. {
  157. items.push_back(new_item);
  158. return NErr_Success;
  159. }
  160. int APEv2::Tag::SetFlags(uint32_t newflags, uint32_t mask)
  161. {
  162. flags = (flags & ~mask) | newflags;
  163. return NErr_Success;
  164. }
  165. /* Removing Data */
  166. void APEv2::Tag::Clear()
  167. {
  168. items.deleteAll();
  169. }
  170. void APEv2::Tag::Remove(const char *key, unsigned int starting_index, int compare)
  171. {
  172. for (ItemList::iterator itr=items.begin();itr!=items.end();)
  173. {
  174. ItemList::iterator next = itr;
  175. next++;
  176. APEv2::Item *item = *itr;
  177. if (item->KeyMatch(key, compare))
  178. {
  179. if (starting_index)
  180. {
  181. starting_index--;
  182. }
  183. else
  184. {
  185. items.erase(item);
  186. delete item;
  187. }
  188. }
  189. itr=next;
  190. }
  191. }
  192. void APEv2::Tag::RemoveItem(Item *item)
  193. {
  194. items.erase(item);
  195. delete item;
  196. }
  197. /* Serializing */
  198. size_t APEv2::Tag::EncodeSize() const
  199. {
  200. size_t total_size=0;
  201. if (flags & FLAG_HEADER_HAS_HEADER)
  202. total_size+=Header::SIZE;
  203. for (ItemList::iterator itr=items.begin();itr!=items.end();itr++)
  204. {
  205. total_size += itr->EncodeSize();
  206. }
  207. if (!(flags & FLAG_HEADER_NO_FOOTER))
  208. total_size+=Header::SIZE;
  209. return total_size;
  210. }
  211. int APEv2::Tag::Encode(void *data, size_t len) const
  212. {
  213. bytewriter_s byte_writer;
  214. bytewriter_init(&byte_writer, data, len);
  215. if (flags & FLAG_HEADER_HAS_HEADER)
  216. {
  217. Header header;
  218. header.SetSize((uint32_t)len - Header::SIZE);
  219. header.SetItems((uint32_t)items.size());
  220. header.SetFlags((flags & FLAG_HEADER_ENCODE_MASK)|FLAG_HEADER_IS_HEADER);
  221. int ret = header.Encode(&byte_writer);
  222. if (ret != NErr_Success)
  223. return ret;
  224. }
  225. for (ItemList::iterator itr=items.begin();itr!=items.end();itr++)
  226. {
  227. int ret = itr->Encode(&byte_writer);
  228. if (ret!= NErr_Success)
  229. return ret;
  230. }
  231. if (!(flags & FLAG_HEADER_NO_FOOTER))
  232. {
  233. Header footer;
  234. if (flags & FLAG_HEADER_HAS_HEADER)
  235. footer.SetSize((uint32_t)len - Header::SIZE);
  236. else
  237. footer.SetSize((uint32_t)len);
  238. footer.SetItems((uint32_t)items.size());
  239. footer.SetFlags((flags & FLAG_HEADER_ENCODE_MASK));
  240. int ret = footer.Encode(&byte_writer);
  241. if (ret != NErr_Success)
  242. return ret;
  243. }
  244. return NErr_Success;
  245. }