1
0

item.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #include "item.h"
  2. #include "flags.h"
  3. #include "util.h"
  4. #include "nu/ByteWriter.h"
  5. #include "nu/strsafe.h"
  6. #include "nu/ByteReader.h"
  7. #include "nsapev2/nsapev2.h"
  8. #include <stdlib.h>
  9. /*
  10. http://wiki.hydrogenaudio.org/index.php?title=APE_Tag_Item
  11. Item layout:
  12. [0-3] length of value field (little endian)
  13. [4-7] flags (little endian)
  14. [null terminated] key
  15. [length] value
  16. */
  17. APEv2::Item::Item()
  18. {
  19. len=0;
  20. flags=0;
  21. key=0;
  22. value=0;
  23. }
  24. APEv2::Item::~Item()
  25. {
  26. free(key);
  27. free(value);
  28. }
  29. int APEv2::Item::Read(bytereader_t byte_reader)
  30. {
  31. if (bytereader_size(byte_reader) < 8)
  32. return NErr_NeedMoreData;
  33. /* read fixed-size fields */
  34. len = bytereader_read_u32_le(byte_reader);
  35. flags = bytereader_read_u32_le(byte_reader);
  36. /* find the null terminator */
  37. size_t key_len = bytereader_find_zero(byte_reader);
  38. /* make sure we didn't hit the end of our buffer */
  39. if (key_len == bytereader_size(byte_reader))
  40. return NErr_Insufficient;
  41. /* check for empty key and also check for integer overflow */
  42. if (key_len == 0 || key_len+1 == 0)
  43. return NErr_Error;
  44. key = (char *)malloc(key_len+1);
  45. if (key)
  46. {
  47. bytereader_read_n(byte_reader, key, key_len+1); /* read key and terminator*/
  48. if (bytereader_size(byte_reader) < len) /* make sure we have room for the value! */
  49. {
  50. free(key);
  51. key=0;
  52. return NErr_NeedMoreData;
  53. }
  54. value = (char *)malloc(len);
  55. if (value)
  56. {
  57. bytereader_read_n(byte_reader, value, len); /* read value */
  58. return NErr_Success;
  59. }
  60. else
  61. {
  62. free(key);
  63. key=0;
  64. return NErr_OutOfMemory;
  65. }
  66. }
  67. else
  68. return NErr_OutOfMemory;
  69. }
  70. bool APEv2::Item::IsReadOnly()
  71. {
  72. return flags & FLAG_READONLY;
  73. }
  74. bool APEv2::Item::KeyMatch(const char *key_to_compare, int compare)
  75. {
  76. if (!key || !*key)
  77. return false;
  78. switch (compare)
  79. {
  80. case ITEM_KEY_COMPARE_CASE_INSENSITIVE:
  81. #ifdef _WIN32
  82. return !_stricmp(key_to_compare, key);
  83. #else
  84. return !strcasecmp(key_to_compare, key);
  85. #endif
  86. case ITEM_KEY_COMPARE_CASE_SENSITIVE:
  87. return !strcmp(key_to_compare, key);
  88. default:
  89. return false;
  90. }
  91. }
  92. int APEv2::Item::Get(const void **data, size_t *datalen) const
  93. {
  94. if (!value || !len)
  95. return NErr_Empty;
  96. *data = value;
  97. *datalen = len;
  98. return NErr_Success;
  99. }
  100. int APEv2::Item::Set(nx_string_t string)
  101. {
  102. if (!value)
  103. return NErr_BadParameter;
  104. flags &= ~nsapev2_item_type_mask;
  105. flags |= nsapev2_item_type_utf8;
  106. size_t bytes;
  107. int ret = NXStringGetBytesSize(&bytes, string, nx_charset_utf8, 0);
  108. if (ret != NErr_DirectPointer && ret != NErr_Success)
  109. return ret;
  110. void *new_value = malloc(bytes);
  111. if (!new_value)
  112. return NErr_OutOfMemory;
  113. size_t bytes_copied;
  114. ret = NXStringGetBytes(&bytes_copied, string, new_value, bytes, nx_charset_utf8, 0);
  115. if (ret != NErr_Success)
  116. {
  117. free(new_value);
  118. return ret;
  119. }
  120. free(value);
  121. value=new_value;
  122. len=(uint32_t)bytes_copied;
  123. return NErr_Success;
  124. }
  125. int APEv2::Item::Set(const void *data, size_t datalen, int data_type)
  126. {
  127. if (!data || !datalen)
  128. return NErr_Error;
  129. // set data type for this item
  130. flags &= ~nsapev2_item_type_mask;
  131. flags |= data_type;
  132. void *new_value = realloc(value, datalen);
  133. if (!new_value)
  134. return NErr_OutOfMemory;
  135. value=new_value;
  136. len=(uint32_t)datalen;
  137. memcpy(value, data, len);
  138. return NErr_Success;
  139. }
  140. int APEv2::Item::New(size_t datalen, int data_type, void **bytes)
  141. {
  142. if (!datalen)
  143. return NErr_Error;
  144. // set data type for this item
  145. flags &= ~nsapev2_item_type_mask;
  146. flags |= data_type;
  147. void *new_value = realloc(value, datalen);
  148. if (!new_value)
  149. return NErr_OutOfMemory;
  150. value=new_value;
  151. len=(uint32_t)datalen;
  152. *bytes = value;
  153. return NErr_Success;
  154. }
  155. int APEv2::Item::SetKey(const char *tag)
  156. {
  157. if (!tag || !*tag)
  158. return NErr_Error;
  159. char *new_key = strdup(tag);
  160. if (!new_key)
  161. return NErr_OutOfMemory;
  162. free(key);
  163. key = new_key;
  164. return NErr_Success;
  165. }
  166. int APEv2::Item::GetKey(const char **tag) const
  167. {
  168. if (!key)
  169. return NErr_Error;
  170. *tag = key;
  171. return NErr_Success;
  172. }
  173. size_t APEv2::Item::EncodeSize() const
  174. {
  175. return 4 /* size */ + 4 /* flags */ + strlen(key) + 1 /* NULL separator */ + len;
  176. }
  177. uint32_t APEv2::Item::GetFlags() const
  178. {
  179. return flags;
  180. }
  181. int APEv2::Item::Encode(bytewriter_t byte_writer) const
  182. {
  183. if (!key || !value || !len)
  184. return NErr_Error;
  185. if (bytewriter_size(byte_writer) < EncodeSize())
  186. return NErr_Insufficient;
  187. bytewriter_write_u32_le(byte_writer, len);
  188. bytewriter_write_u32_le(byte_writer, flags);
  189. bytewriter_write_n(byte_writer, key, strlen(key) + 1);
  190. bytewriter_write_n(byte_writer, value, len);
  191. return NErr_Success;
  192. }