19#include "id3dependencies/ByteStream/include/byteInt.h"
20#include "id3dependencies/ByteStream/include/byteUnicode.h"
21#include "id3dependencies/ByteStream/include/byteStream.h"
23static char *internal_base64Encode(
const unsigned char *input,
size_t inputLength) {
24 static const unsigned char base64Chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
25 const size_t outputLength = 4 * ((inputLength + 2) / 3);
26 unsigned char *output = malloc(outputLength + 1);
34 for (i = 0, j = 0; i < inputLength; i += 3, j += 4) {
35 const unsigned int byte1 = input[i];
36 const unsigned int byte2 = (i + 1 < inputLength) ? input[i + 1] : 0;
37 const unsigned int byte3 = (i + 2 < inputLength) ? input[i + 2] : 0;
39 output[j] = base64Chars[byte1 >> 2];
40 output[j + 1] = base64Chars[((byte1 & 0x03) << 4) | (byte2 >> 4)];
41 output[j + 2] = (i + 1 < inputLength) ? base64Chars[((byte2 & 0x0F) << 2) | (byte3 >> 6)] : (unsigned char)
'=';
42 output[j + 3] = (i + 2 < inputLength) ? base64Chars[byte3 & 0x3F] : (
unsigned char)
'=';
45 output[outputLength] =
'\0';
46 return (
char *) output;
69 bool readOnly,
bool unsync, uint32_t decompressionSize,
70 uint8_t encryptionSymbol, uint8_t groupSymbol) {
122 void *tmp = malloc(size);
123 memcpy(tmp, entry, size);
149 if (one == NULL || two == NULL) {
155 for (
size_t i = 0; i < usableSize; i++) {
156 if (((
unsigned char *) one->
entry)[i] != ((
unsigned char *) two->
entry)[i]) {
157 diff = ((
unsigned char *) one->
entry)[i] - ((
unsigned char *) two->
entry)[i];
177 const int memCount = snprintf(NULL, 0,
"Size: %zu, data: %p\n", e->
size, e->
entry);
179 char *str = calloc(memCount + 1,
sizeof(
char));
181 (void) snprintf(str, memCount,
"Size: %zu, data: %p\n", e->
size, e->
entry);
213 if (e->
entry != NULL) {
298 i1 = listCreateIterator(f->
entries);
299 i2 = listCreateIterator(s->
entries);
301 while ((tmp1 = listIteratorNext(&i1)) != NULL) {
302 tmp2 = listIteratorNext(&i2);
316 i1 = listCreateIterator(f->
contexts);
317 i2 = listCreateIterator(s->
contexts);
319 while ((tmp1 = listIteratorNext(&i1)) != NULL) {
320 tmp2 = listIteratorNext(&i2);
345 const int memCount = snprintf(NULL, 0,
"header : %p, context : %p, entries : %p", f->
header, f->
contexts,
348 s = calloc(memCount + 1,
sizeof(
char));
350 (void) snprintf(s, memCount,
"header : %p, context : %p, entries : %p", f->
header, f->
contexts, f->
entries);
411 listFree((*toDelete)->contexts);
412 listFree((*toDelete)->entries);
440 HashTable *pairs = NULL;
441 List *context = NULL;
442 List *entries = NULL;
450 context = hashTableRetrieve(pairs,
id);
453 if (context == NULL &&
id[0] ==
'T') {
454 context = hashTableRetrieve(pairs,
"T");
458 if (context == NULL &&
id[0] ==
'W') {
459 context = hashTableRetrieve(pairs,
"W");
463 if (context == NULL) {
464 context = hashTableRetrieve(userPairs,
id);
468 if (context == NULL) {
469 context = hashTableRetrieve(pairs,
"?");
473 ListIter i = listCreateIterator(context);
477 while ((cc = listIteratorNext(&i)) != NULL) {
480 listInsertBack(entries, (
void *) ce);
487 hashTableFree(pairs);
506 if (frame->
header == NULL) {
532 if (tag->
frames == NULL) {
536 return listCreateIterator(tag->
frames);
550 return (
Id3v2Frame *) listIteratorNext(traverser);
575 return listCreateIterator(frame->
entries);
592 if (traverser == NULL) {
611 ret = malloc(data->
size);
612 memset(ret, 0, data->
size);
615 *dataSize = data->
size;
633 unsigned char *tmp = NULL;
634 unsigned char *outString = NULL;
635 unsigned char encoding = 0;
636 char *escapedStr = NULL;
638 int utf8BomOffset = 0;
650 if (*dataSize > BYTE_BOM_SIZE) {
651 if (byteHasBOM(tmp)) {
652 if (tmp[0] == 0xff && tmp[1] == 0xfe) {
653 encoding = BYTE_UTF16LE;
655 encoding = BYTE_UTF16BE;
661 unsigned char *reallocPtr = realloc(tmp, *dataSize + (
size_t) (BYTE_PADDING * 2));
663 if (reallocPtr == NULL) {
671 memset(tmp + *dataSize, 0, (
size_t) (BYTE_PADDING * 2));
672 outLen = *dataSize + (size_t) (BYTE_PADDING * 2);
675 if (byteIsUtf8(tmp)) {
676 encoding = BYTE_UTF8;
680 if (byteIsUtf8(tmp) && encoding == 0) {
681 encoding = BYTE_ISO_8859_1;
685 convi = byteConvertTextFormat(tmp, encoding, *dataSize + (
size_t) (BYTE_PADDING * 2), &outString, BYTE_UTF8,
688 if (!convi && outLen == 0) {
695 if (convi && outLen == 0) {
703 if (*dataSize >= 3 && outString[0] == 0xEF && outString[1] == 0xBB && outString[2] == 0xBF) {
708 escapedStr = malloc((2 * (*dataSize - utf8BomOffset)) + 1);
711 for (
size_t i = 0; i < *dataSize - utf8BomOffset; i++) {
712 if (outString[i + utf8BomOffset] ==
'"' || outString[i + utf8BomOffset] ==
'\\') {
713 escapedStr[j++] =
'\\';
714 escapedStr[j++] = (char) outString[i + utf8BomOffset];
716 escapedStr[j++] = (char) outString[i + utf8BomOffset];
720 escapedStr[j] =
'\0';
725 while (escapedStr[nullPos] !=
'\0') {
729 escapedStr[nullPos] =
'\0';
731 if (*dataSize == 0) {
779 unsigned char *tmp = NULL;
791 if (dataSize >=
sizeof(uint16_t)) {
792 ret = (uint16_t) tmp[1] << 8 | (uint16_t) tmp[0];
793 }
else if (dataSize ==
sizeof(uint8_t)) {
794 ret = (uint16_t) tmp[0];
813 unsigned char *tmp = NULL;
824 if (dataSize >
sizeof(uint32_t)) {
825 dataSize =
sizeof(uint32_t);
833 ret = tmp[1] | (tmp[0] << 8);
836 ret = tmp[2] | (tmp[1] << 8) | (tmp[0] << 16);
839 ret = tmp[3] | (tmp[2] << 8) | (tmp[1] << 16) | (tmp[0] << 24);
866 if (frame == NULL || entries == NULL || entrySize == 0 || entry == NULL) {
870 if (frame->
contexts == NULL || frame->
entries == NULL || entries->current == NULL) {
875 ListIter contextIter = listCreateIterator(frame->
contexts);
876 ListIter entriesIter = listCreateIterator(frame->
entries);
886 const int comp = frame->
entries->compareData((
void *) ce, entries->current->data);
903 poscc = (poscc == 0) ? 0 : poscc - 1;
906 if (poscc == posce) {
919 if (entrySize > cc->
max) {
923 if (entrySize < cc->min) {
928 newData = malloc(newSize);
929 memset(newData, 0, newSize);
930 memcpy(newData, entry, newSize);
954 if (tag == NULL || frame == NULL) {
962 return listInsertBack(tag->
frames, (
void *) frame) ? true :
false;
979 if (tag == NULL || frame == NULL) {
983 return listDeleteData(tag->
frames, (
void *) frame);
1003 unsigned char *tmp = NULL;
1004 ByteStream *stream = NULL;
1005 uint8_t *out = NULL;
1016 stream = byteStreamCreate(NULL, 6);
1020 tmp = u32tob(frameSize);
1021 byteStreamWrite(stream, tmp + 1, 3);
1028 stream = byteStreamCreate(NULL, 10);
1032 tmp = u32tob(frameSize);
1033 byteStreamWrite(stream, tmp, 4);
1038 byteStreamWriteBit(stream, header->
readOnly, 5);
1039 byteStreamSeek(stream, 1, SEEK_CUR);
1042 byteStreamWriteBit(stream, (header->
encryptionSymbol > 0) ?
true :
false, 6);
1043 byteStreamWriteBit(stream, (header->
groupSymbol > 0) ?
true :
false, 5);
1044 byteStreamSeek(stream, 1, SEEK_CUR);
1047 byteStreamResize(stream, stream->bufferSize + 4);
1049 byteStreamWrite(stream, tmp, 4);
1054 byteStreamResize(stream, stream->bufferSize + 1);
1059 byteStreamResize(stream, stream->bufferSize + 1);
1067 stream = byteStreamCreate(NULL, 10);
1071 tmp = u32tob(byteSyncintEncode(frameSize));
1072 byteStreamWrite(stream, tmp, 4);
1077 byteStreamWriteBit(stream, header->
readOnly, 4);
1078 byteStreamSeek(stream, 1, SEEK_CUR);
1080 byteStreamWriteBit(stream, (header->
groupSymbol > 0) ?
true :
false, 6);
1082 byteStreamWriteBit(stream, (header->
encryptionSymbol > 0) ?
true :
false, 2);
1085 byteStreamSeek(stream, 1, SEEK_CUR);
1088 byteStreamResize(stream, stream->bufferSize + 1);
1093 byteStreamResize(stream, stream->bufferSize + 1);
1098 byteStreamResize(stream, stream->bufferSize + 4);
1100 byteStreamWrite(stream, tmp, 4);
1111 byteStreamRewind(stream);
1112 out = calloc(stream->bufferSize,
sizeof(uint8_t));
1113 *outl = stream->bufferSize;
1114 byteStreamRead(stream, out, stream->bufferSize);
1115 byteStreamDestroy(stream);
1138 size_t memCount = 3;
1140 if (header == NULL) {
1141 json = calloc(memCount,
sizeof(
char));
1142 memcpy(json,
"{}\0", memCount);
1149 memCount += snprintf(NULL, 0,
1150 "{\"id\":\"%c%c%c\"}",
1155 json = calloc(memCount + 1,
sizeof(
char));
1157 (void) snprintf(json, memCount,
1158 "{\"id\":\"%c%c%c\"}",
1166 memCount += snprintf(NULL, 0,
1167 "{\"id\":\"%c%c%c%c\",\"tagAlterPreservation\":%s,\"fileAlterPreservation\":%s,\"readOnly\":%s,\"decompressionSize\":%"
1168 PRId32
",\"encryptionSymbol\":%d,\"groupSymbol\":%d}",
1175 ((header->
readOnly ==
true) ?
"true" :
"false"),
1180 json = calloc(memCount + 1,
sizeof(
char));
1182 (void) snprintf(json, memCount,
1183 "{\"id\":\"%c%c%c%c\",\"tagAlterPreservation\":%s,\"fileAlterPreservation\":%s,\"readOnly\":%s,\"decompressionSize\":%"
1184 PRId32
",\"encryptionSymbol\":%d,\"groupSymbol\":%d}",
1191 ((header->
readOnly ==
true) ?
"true" :
"false"),
1199 memCount += snprintf(NULL, 0,
1200 "{\"id\":\"%c%c%c%c\",\"tagAlterPreservation\":%s,\"fileAlterPreservation\":%s,\"readOnly\":%s,\"unsynchronisation\":%s,\"decompressionSize\":%"
1201 PRId32
",\"encryptionSymbol\":%d,\"groupSymbol\":%d}",
1208 ((header->
readOnly ==
true) ?
"true" :
"false"),
1214 json = calloc(memCount + 1,
sizeof(
char));
1216 (void) snprintf(json, memCount,
1217 "{\"id\":\"%c%c%c%c\",\"tagAlterPreservation\":%s,\"fileAlterPreservation\":%s,\"readOnly\":%s,\"unsynchronisation\":%s,\"decompressionSize\":%"
1218 PRId32
",\"encryptionSymbol\":%d,\"groupSymbol\":%d}",
1225 ((header->
readOnly ==
true) ?
"true" :
"false"),
1235 json = calloc(memCount,
sizeof(
char));
1236 memcpy(json,
"{}\0", memCount);
1261 ByteStream *stream = NULL;
1269 ListIter context = listCreateIterator(frame->
contexts);
1271 ListIter iterStorage;
1272 size_t readSize = 0;
1273 size_t contentSize = 0;
1274 size_t currIterations = 0;
1275 size_t headerSize = 0;
1276 uint8_t *header = NULL;
1277 uint8_t *out = NULL;
1278 unsigned char *tmp = NULL;
1280 bool bitFlag =
false;
1285 stream = byteStreamCreate(header, headerSize);
1288 byteStreamSeek(stream, 0, SEEK_END);
1290 while ((cc = listIteratorNext(&context)) != NULL) {
1294 ListIter contentContextIter = listCreateIterator(frame->
contexts);
1295 ListIter contentEntryIter = listCreateIterator(frame->
entries);
1299 uint8_t encoding = 0;
1300 void *iterNext = NULL;
1304 while ((iterNext = listIteratorNext(&contentContextIter)) != NULL) {
1317 while ((iterNext = listIteratorNext(&contentEntryIter)) != NULL) {
1318 if (poscc == posce) {
1329 if (tmp == NULL || utf8Len == 0) {
1334 unsigned char *outStr = NULL;
1338 if (utf8Len >= 1 && tmp[0] != 0) {
1340 convi = byteConvertTextFormat(tmp, BYTE_UTF8, utf8Len, &outStr, encoding, &outLen);
1342 if (convi ==
false && outLen == 0) {
1350 if (convi && outLen == 0) {
1358 if (encoding == BYTE_UTF16BE || encoding == BYTE_UTF16LE) {
1359 bytePrependBOM(encoding, &outStr, &outLen);
1366 if (trav.current != NULL) {
1368 case BYTE_ISO_8859_1:
1371 unsigned char *reallocPtr = realloc(outStr, outLen + 1);
1372 if (reallocPtr == NULL) {
1374 byteStreamDestroy(stream);
1378 outStr = reallocPtr;
1379 memset(outStr + outLen, 0, 1);
1384 case BYTE_UTF16LE: {
1385 unsigned char *reallocPtr = realloc(outStr, outLen + 2);
1386 if (reallocPtr == NULL) {
1388 byteStreamDestroy(stream);
1392 outStr = reallocPtr;
1393 memset(outStr + outLen, 0, 2);
1402 byteStreamResize(stream, stream->bufferSize + outLen);
1403 byteStreamWrite(stream, outStr, outLen);
1404 contentSize += outLen;
1422 byteStreamResize(stream, stream->bufferSize + readSize);
1423 byteStreamWrite(stream, tmp, readSize);
1425 contentSize += readSize;
1431 unsigned char *outStr = NULL;
1443 convi = byteConvertTextFormat(tmp, BYTE_UTF8, utf8len, &outStr, BYTE_ISO_8859_1, &outLen);
1445 if (convi ==
false && outLen == 0) {
1451 if (convi && outLen == 0) {
1459 if (trav.current != NULL) {
1460 unsigned char *reallocPtr = realloc(outStr, outLen + 1);
1461 if (reallocPtr == NULL) {
1463 byteStreamDestroy(stream);
1467 outStr = reallocPtr;
1468 memset(outStr + outLen, 0, 1);
1472 byteStreamResize(stream, stream->bufferSize + outLen);
1473 byteStreamWrite(stream, outStr, outLen);
1476 contentSize += outLen;
1482 if (currIterations == 0) {
1483 iterStorage = context;
1485 context = listCreateIterator(frame->
contexts);
1487 for (
size_t i = 0; i < cc->
min; i++) {
1488 listIteratorNext(&context);
1493 if (currIterations != cc->
max && currIterations != 0) {
1494 context = listCreateIterator(frame->
contexts);
1496 for (
size_t i = 0; i < cc->
min; i++) {
1497 listIteratorNext(&context);
1502 if (currIterations >= cc->
max) {
1503 context = iterStorage;
1505 for (
size_t i = 0; i < currIterations; i++) {
1506 listIteratorNext(&context);
1523 if (listIteratorHasNext(context)) {
1533 if (bitFlag ==
true) {
1534 unsigned char *bitBuff = NULL;
1535 unsigned char **byteDataArr = NULL;
1536 size_t *byteDataSizeArr = NULL;
1537 size_t *nbits = NULL;
1540 size_t totalBits = 0;
1541 size_t totalBytes = 0;
1542 size_t bitBuffSize = 0;
1553 if (byteDataSizeArr == NULL) {
1554 byteDataSizeArr = malloc(
sizeof(
size_t));
1555 byteDataSizeArr[0] = readSize;
1557 nbits = malloc(
sizeof(
size_t));
1560 byteDataArr = (
unsigned char **) malloc(
sizeof(
unsigned char *));
1561 byteDataArr[0] = malloc(readSize);
1563 for (
size_t i = 0; i < readSize; i++) {
1564 byteDataArr[0][i] = tmp[i];
1570 byteDataSizeArr = realloc(byteDataSizeArr, arrSize *
sizeof(
size_t));
1571 byteDataSizeArr[arrSize - 1] = readSize;
1573 nbits = realloc(nbits, arrSize *
sizeof(
size_t));
1574 nbits[arrSize - 1] = cc->
max;
1576 byteDataArr = realloc(byteDataArr, arrSize *
sizeof(
unsigned char *));
1577 byteDataArr[arrSize - 1] = malloc(readSize);
1579 for (
size_t i = 0; i < readSize; i++) {
1580 byteDataArr[arrSize - 1][i] = tmp[i];
1584 totalBits += cc->
max;
1589 if (listIteratorHasNext(context)) {
1595 cc = listIteratorNext(&context);
1602 totalBytes = ((totalBits / CHAR_BIT) % 2) ? (totalBits / CHAR_BIT) + 1 : totalBits / CHAR_BIT;
1605 bitBuff = malloc(totalBytes);
1606 memset(bitBuff, 0, totalBytes);
1607 bitBuffSize = totalBytes;
1610 for (
size_t i = 0; i < arrSize; i++) {
1611 size_t dataSize = byteDataSizeArr[i];
1612 size_t halfSize = dataSize / 2;
1613 for (
size_t j = 0; j < halfSize; j++) {
1614 unsigned char temp = byteDataArr[i][j];
1615 byteDataArr[i][j] = byteDataArr[i][dataSize - j - 1];
1616 byteDataArr[i][dataSize - j - 1] = temp;
1623 for (
size_t i = totalBytes; i > 0; i--) {
1624 if (step >= arrSize || totalBytes == 0) {
1628 size_t nBit = nbits[step];
1629 size_t nBytes = byteDataSizeArr[step];
1630 unsigned char *data = byteDataArr[step];
1634 if (counter == nBytes) {
1639 for (j = 0; j < CHAR_BIT; j++) {
1645 if (j + offset >= CHAR_BIT) {
1651 bitBuff[totalBytes - 1] = setBit(bitBuff[totalBytes - 1], bitIndex,
1652 readBit(data[counter], j) > 0 ?
true :
false);
1669 byteStreamResize(stream, stream->bufferSize + bitBuffSize);
1670 byteStreamWrite(stream, bitBuff, bitBuffSize);
1671 contentSize += bitBuffSize;
1673 for (
size_t i = 0; i < arrSize; i++) {
1674 free(byteDataArr[i]);
1680 free(byteDataSizeArr);
1686 int totalBytesNeeded = (cc->
max / CHAR_BIT) + 1;
1687 int nBit = CHAR_BIT - 1;
1696 while (totalBytesNeeded > 0) {
1697 byteStreamResize(stream, stream->bufferSize + 1);
1700 byteStreamWriteBit(stream, (readBit(tmp[readSize - 1], nBit) > 0) ?
true :
false, nBit);
1704 byteStreamSeek(stream, 1, SEEK_CUR);
1708 contentSize += readSize;
1716 ListIter contentContextIter = listCreateIterator(frame->
contexts);
1717 ListIter contentEntryIter = listCreateIterator(frame->
entries);
1721 void *iterNext = NULL;
1725 while ((iterNext = listIteratorNext(&contentContextIter)) != NULL) {
1738 while ((iterNext = listIteratorNext(&contentEntryIter)) != NULL) {
1739 if (poscc == posce) {
1755 byteStreamResize(stream, stream->bufferSize + rSize);
1756 byteStreamWrite(stream, tmp, rSize);
1758 contentSize += rSize;
1777 tmp = u32tob(contentSize);
1784 tmp = u32tob(contentSize);
1791 tmp = u32tob(byteSyncintEncode(contentSize));
1801 byteStreamRewind(stream);
1802 *outl = stream->bufferSize;
1803 out = calloc(stream->bufferSize,
sizeof(uint8_t));
1804 byteStreamRead(stream, out, stream->bufferSize);
1805 byteStreamDestroy(stream);
1845 char *headerJson = NULL;
1846 char **contentJson = NULL;
1847 char *concatenatedString = NULL;
1848 size_t contentJsonSize = 0;
1849 size_t memCount = 3;
1850 size_t concatenatedStringLength = 0;
1851 size_t currIterations = 0;
1854 ListIter context = listCreateIterator(frame->
contexts);
1855 ListIter iterStorage;
1861 unsigned char *tmp = NULL;
1864 json = calloc(memCount,
sizeof(
char));
1865 memcpy(json,
"{}\0", memCount);
1875 size_t readSize = 0;
1876 size_t contentMemCount = 3;
1881 if (tmp == NULL || readSize == 0) {
1887 b64 = internal_base64Encode(tmp, readSize);
1889 contentMemCount += snprintf(NULL, 0,
1890 "{\"value\":\"%s\",\"size\":%zu}",
1895 if (contentJson == NULL) {
1896 contentJson = (
char **) calloc(contentJsonSize,
sizeof(
char *));
1897 contentJson[contentJsonSize - 1] = calloc(contentMemCount + 1,
sizeof(
char));
1899 (void) snprintf(contentJson[contentJsonSize - 1], contentMemCount,
1900 "{\"value\":\"%s\",\"size\":%zu}",
1904 char **reallocContentJson = (
char **) realloc((
void *) contentJson,
1905 (contentJsonSize) *
sizeof(
char *));
1907 if (reallocContentJson == NULL) {
1908 for (
size_t i = 0; i < contentJsonSize - 1; i++) {
1909 free(contentJson[i]);
1911 free((
void *) contentJson);
1917 contentJson = reallocContentJson;
1918 contentJson[contentJsonSize - 1] = calloc(contentMemCount + 1,
sizeof(
char));
1919 (void) snprintf(contentJson[contentJsonSize - 1], contentMemCount,
1920 "{\"value\":\"%s\",\"size\":%zu}",
1934 size_t readSize = 0;
1935 size_t contentMemCount = 3;
1939 if (tmp == NULL || readSize == 0) {
1945 contentMemCount += snprintf(NULL, 0,
1946 "{\"value\":\"%s\",\"size\":%zu}",
1951 if (contentJson == NULL) {
1952 contentJson = (
char **) calloc(contentJsonSize,
sizeof(
char *));
1953 contentJson[contentJsonSize - 1] = calloc(contentMemCount + 1,
sizeof(
char));
1955 (void) snprintf(contentJson[contentJsonSize - 1], contentMemCount,
1956 "{\"value\":\"%s\",\"size\":%zu}",
1960 char **reallocContentJson = (
char **) realloc((
void *) contentJson,
1961 (contentJsonSize) *
sizeof(
char *));
1963 if (reallocContentJson == NULL) {
1964 for (
size_t i = 0; i < contentJsonSize - 1; i++) {
1965 free(contentJson[i]);
1967 free((
void *) contentJson);
1972 contentJson = reallocContentJson;
1973 contentJson[contentJsonSize - 1] = calloc(contentMemCount + 1,
sizeof(
char));
1974 (void) snprintf(contentJson[contentJsonSize - 1], contentMemCount,
1975 "{\"value\":\"%s\",\"size\":%zu}",
1985 size_t readSize = 0;
1986 size_t contentMemCount = 3;
1991 if (tmp == NULL || readSize == 0) {
1996 num = btost(tmp, (
int) readSize);
1999 contentMemCount += snprintf(NULL, 0,
2000 "{\"value\":\"%zu\",\"size\":%zu}",
2005 if (contentJson == NULL) {
2006 contentJson = (
char **) calloc(contentJsonSize,
sizeof(
char *));
2007 contentJson[contentJsonSize - 1] = calloc(contentMemCount + 1,
sizeof(
char));
2009 (void) snprintf(contentJson[contentJsonSize - 1], contentMemCount,
2010 "{\"value\":\"%zu\",\"size\":%zu}",
2014 char **reallocContentJson = (
char **) realloc((
void *) contentJson,
2015 (contentJsonSize) *
sizeof(
char *));
2017 if (reallocContentJson == NULL) {
2018 for (
size_t i = 0; i < contentJsonSize - 1; i++) {
2019 free(contentJson[i]);
2021 free((
void *) contentJson);
2025 contentJson = reallocContentJson;
2026 contentJson[contentJsonSize - 1] = calloc(contentMemCount + 1,
sizeof(
char));
2027 (void) snprintf(contentJson[contentJsonSize - 1], contentMemCount,
2028 "{\"value\":\"%zu\",\"size\":%zu}",
2036 size_t readSize = 0;
2037 size_t contentMemCount = 0;
2042 if (tmp == NULL || readSize == 0) {
2048 memcpy(&value, tmp,
sizeof(value));
2051 contentMemCount = snprintf(NULL, 0,
2052 "{\"value\":\"%f\",\"size\":%zu}",
2057 if (contentJson == NULL) {
2058 contentJson = (
char **) calloc(contentJsonSize,
sizeof(
char *));
2059 contentJson[contentJsonSize - 1] = calloc(contentMemCount + 1,
sizeof(
char));
2061 (void) snprintf(contentJson[contentJsonSize - 1], contentMemCount,
2062 "{\"value\":\"%f\",\"size\":%zu}",
2066 char **reallocContentJson = (
char **) realloc((
void *) contentJson,
2067 (contentJsonSize) *
sizeof(
char *));
2069 if (reallocContentJson == NULL) {
2070 for (
size_t i = 0; i < contentJsonSize - 1; i++) {
2071 free(contentJson[i]);
2073 free((
void *) contentJson);
2076 contentJson = reallocContentJson;
2077 contentJson[contentJsonSize - 1] = calloc(contentMemCount + 1,
sizeof(
char));
2078 (void) snprintf(contentJson[contentJsonSize - 1], contentMemCount,
2079 "{\"value\":\"%f\",\"size\":%zu}",
2089 if (currIterations == 0) {
2090 iterStorage = context;
2092 context = listCreateIterator(frame->
contexts);
2094 for (
size_t i = 0; i < cc->
min; i++) {
2095 listIteratorNext(&context);
2100 if (currIterations != cc->
max && currIterations != 0) {
2101 context = listCreateIterator(frame->
contexts);
2103 for (
size_t i = 0; i < cc->
min; i++) {
2104 listIteratorNext(&context);
2109 if (currIterations >= cc->
max) {
2110 context = iterStorage;
2112 for (
size_t i = 0; i < currIterations; i++) {
2113 listIteratorNext(&context);
2129 ListIter contentContextIter = listCreateIterator(frame->
contexts);
2130 ListIter contentEntryIter = listCreateIterator(frame->
entries);
2133 size_t readSize = 0;
2134 size_t contentMemCount = 0;
2135 void *iterNext = NULL;
2140 while ((iterNext = listIteratorNext(&contentContextIter)) != NULL) {
2153 while ((iterNext = listIteratorNext(&contentEntryIter)) != NULL) {
2154 if (poscc == posce) {
2166 if (tmp == NULL || readSize == 0) {
2172 b64 = internal_base64Encode(tmp, readSize);
2176 contentMemCount = snprintf(NULL, 0,
2177 "{\"value\":\"%s\",\"size\":%zu}",
2182 if (contentJson == NULL) {
2183 contentJson = (
char **) calloc(contentJsonSize,
sizeof(
char *));
2184 contentJson[contentJsonSize - 1] = calloc(contentMemCount + 1,
sizeof(
char));
2186 (void) snprintf(contentJson[contentJsonSize - 1], contentMemCount,
2187 "{\"value\":\"%s\",\"size\":%zu}",
2191 char **reallocContentJson = (
char **) realloc((
void *) contentJson,
2192 (contentJsonSize) *
sizeof(
char *));
2194 if (reallocContentJson == NULL) {
2195 for (
size_t i = 0; i < contentJsonSize - 1; i++) {
2196 free(contentJson[i]);
2198 free((
void *) contentJson);
2202 contentJson = reallocContentJson;
2203 contentJson[contentJsonSize - 1] = calloc(contentMemCount + 1,
sizeof(
char));
2204 (void) snprintf(contentJson[contentJsonSize - 1], contentMemCount,
2205 "{\"value\":\"%s\",\"size\":%zu}",
2228 if (contentJson != NULL) {
2229 for (
size_t i = 0; i < contentJsonSize; i++) {
2230 concatenatedStringLength += strlen(contentJson[i]) + 1;
2233 concatenatedString = calloc(concatenatedStringLength + 1,
sizeof(
char));
2236 for (
size_t i = 0; i < contentJsonSize; i++) {
2238 concatenatedString[offset++] =
',';
2241 size_t currentLen = strlen(contentJson[i]);
2242 memcpy(concatenatedString + offset, contentJson[i], currentLen);
2243 offset += currentLen;
2245 concatenatedString[offset] =
'\0';
2248 memCount += snprintf(NULL, 0,
2249 "{\"header\":%s,\"content\":[%s]}",
2251 concatenatedString);
2253 json = calloc(memCount + 1,
sizeof(
char));
2254 (void) snprintf(json, memCount,
2255 "{\"header\":%s,\"content\":[%s]}",
2257 concatenatedString);
2262 if (concatenatedString != NULL) {
2263 free(concatenatedString);
2266 if (contentJson != NULL) {
2267 for (
size_t i = 0; i < contentJsonSize; i++) {
2268 free(contentJson[i]);
2270 free((
void *) contentJson);
Function definitions for ID3v2 frame context definitions and parsing configuration.
unsigned long id3v2djb2(const char *str)
Computes a DJB2 hash value for a null-terminated string.
HashTable * id3v2CreateDefaultIdentifierContextPairings(unsigned int version)
Creates a default mapping of frame identifiers to their corresponding parse contexts for all ID3v2 ve...
int id3v2CompareContentContext(const void *first, const void *second)
Performs comparison of two content context structures.
char * id3v2FrameHeaderToJSON(const Id3v2FrameHeader *header, uint8_t version)
Converts a frame header structure to its JSON representation based on ID3v2 version.
int id3v2CompareFrame(const void *first, const void *second)
Performs deep comparison of two ID3v2 frame structures.
bool id3v2WriteFrameEntry(Id3v2Frame *frame, ListIter *entries, size_t entrySize, const void *entry)
Writes data to the entry at the iterator's current position, clamping size to context constraints.
uint8_t * id3v2FrameSerialize(Id3v2Frame *frame, uint8_t version, size_t *outl)
Serializes a complete ID3v2 frame to binary format according to the specified version.
void * id3v2CopyContentEntry(const void *toBeCopied)
Creates a deep copy of a content entry.
ListIter id3v2CreateFrameTraverser(Id3v2Tag *tag)
Creates a list iterator for traversing frames in an ID3v2 tag.
uint32_t id3v2ReadFrameEntryAsU32(ListIter *traverser)
Reads the current entry as a 32-bit unsigned integer, advancing the iterator.
char * id3v2FrameToJSON(Id3v2Frame *frame, uint8_t version)
Converts a complete ID3v2 frame structure to its JSON representation.
void * id3v2ReadFrameEntry(ListIter *traverser, size_t *dataSize)
Reads and returns a deep copy of the current entry's data, advancing the iterator.
Id3v2Frame * id3v2CreateEmptyFrame(const char id[ID3V2_FRAME_ID_MAX_SIZE], uint8_t version, HashTable *userPairs)
Creates an empty frame structure with zero-initialized entries based on context lookup.
uint8_t * id3v2FrameHeaderSerialize(Id3v2FrameHeader *header, uint8_t version, uint32_t frameSize, size_t *outl)
Serializes a frame header to binary format according to the specified ID3v2 version.
Id3v2FrameHeader * id3v2CreateFrameHeader(uint8_t id[ID3V2_FRAME_ID_MAX_SIZE], bool tagAlter, bool fileAlter, bool readOnly, bool unsync, uint32_t decompressionSize, uint8_t encryptionSymbol, uint8_t groupSymbol)
Creates an ID3v2 frame header structure with specified flags and metadata.
bool id3v2AttachFrameToTag(Id3v2Tag *tag, Id3v2Frame *frame)
Inserts a frame at the end of a tag's frames list.
char * id3v2ReadFrameEntryAsChar(ListIter *traverser, size_t *dataSize)
Reads a frame entry as a UTF-8 encoded string with escaped special characters, advancing the iterator...
Id3v2Frame * id3v2CreateFrame(Id3v2FrameHeader *header, List *context, List *entries)
Creates an ID3v2 frame structure from provided components.
ListIter id3v2CreateFrameEntryTraverser(Id3v2Frame *frame)
Creates a list iterator for traversing content entries within a frame.
void * id3v2CopyFrame(const void *toBeCopied)
Creates a deep copy of an ID3v2 frame structure.
Id3v2ContentEntry * id3v2CreateContentEntry(void *entry, size_t size)
Creates a content entry structure with a deep copy of the provided data.
char * id3v2PrintContentEntry(const void *toBePrinted)
Generates a string representation of a content entry for debugging.
void id3v2DestroyFrame(Id3v2Frame **toDelete)
Frees all memory allocated for an ID3v2 frame structure and nullifies the pointer.
void id3v2DeleteContentEntry(void *toBeDeleted)
Frees all memory allocated for a content entry structure.
int id3v2CompareContentEntry(const void *first, const void *second)
Compares two content entries byte-by-byte and returns the difference.
void id3v2DestroyFrameHeader(Id3v2FrameHeader **toDelete)
Frees all memory allocated for a frame header and nullifies the pointer.
Id3v2Frame * id3v2DetachFrameFromTag(Id3v2Tag *tag, Id3v2Frame *frame)
Removes a frame from a tag's frames list and returns it to the caller.
uint8_t id3v2ReadFrameEntryAsU8(ListIter *traverser)
Reads the first byte of the current entry as an 8-bit unsigned integer, advancing the iterator.
char * id3v2PrintFrame(const void *toBePrinted)
Generates a string representation of a frame for debugging.
bool id3v2CompareFrameId(const Id3v2Frame *frame, const char id[ID3V2_FRAME_ID_MAX_SIZE])
Compares a frame's identifier with a provided ID string.
Id3v2Frame * id3v2FrameTraverse(ListIter *traverser)
Advances the iterator and returns the next frame in the list.
void id3v2DeleteFrame(void *toBeDeleted)
Frees all memory allocated for an ID3v2 frame structure.
uint16_t id3v2ReadFrameEntryAsU16(ListIter *traverser)
Reads the current entry as a 16-bit unsigned integer, advancing the iterator.
Function definitions for ID3v2 frame lifecycle, traversal, serialization, and content management.
void * id3v2CopyContentEntry(const void *toBeCopied)
Creates a deep copy of a content entry.
char * id3v2PrintContentEntry(const void *toBePrinted)
Generates a string representation of a content entry for debugging.
void id3v2DeleteContentEntry(void *toBeDeleted)
Frees all memory allocated for a content entry structure.
int id3v2CompareContentEntry(const void *first, const void *second)
Compares two content entries byte-by-byte and returns the difference.
#define ID3V2_TAG_VERSION_3
ID3v2.3 major version number (3)
struct _Id3v2ContentEntry Id3v2ContentEntry
Parsed data field from an ID3v2 frame.
struct _Id3v2ContentContext Id3v2ContentContext
Parsing instructions for a single field within an ID3v2 frame.
struct _Id3v2Tag Id3v2Tag
Complete ID3v2 tag structure containing header and metadata frames.
#define ID3V2_FRAME_ID_MAX_SIZE
Maximum size in bytes for a frame ID field (4 bytes).
#define ID3V2_TAG_VERSION_2
ID3v2.2 major version number (2)
@ noEncoding_context
Raw character data with no encoding or null terminator.
@ iter_context
Iterator for repeating context sequences.
@ numeric_context
Integer values of 8, 16, 32, or 64 bits.
@ encodedString_context
Text string with encoding determined by prior context with the key 'encoding'.
@ latin1Encoding_context
Latin-1 (ISO-8859-1) null-terminated string.
@ adjustment_context
Dynamic upper bound adjustment based on prior context with key 'adjustment'.
@ binary_context
Binary data block with no terminator.
@ bit_context
Bit-level field (1-8 bits).
@ precision_context
Floating-point values (float or double).
@ unknown_context
Error/invalid context state (-1).
struct _Id3v2Frame Id3v2Frame
Complete ID3v2 frame structure with header, parsing contexts, and data.
#define ID3V2_TAG_VERSION_4
ID3v2.4 major version number (4)
struct _Id3v2FrameHeader Id3v2FrameHeader
ID3v2 frame header containing identification and processing flags.
size_t min
Minimum size in bytes (or bits for bit_context, or start index for iter_context).
size_t max
Maximum size in bytes (or bits for bit_context, or iteration count for iter_context).
Id3v2ContextType type
Context type determining parsing behavior (string, binary, numeric, etc.)
size_t size
Size in bytes of the data pointed to by entry.
void * entry
Pointer to extracted field data (string, binary, numeric, etc.). Type determined by corresponding con...
Id3v2FrameHeader * header
Frame header containing ID, flags, and processing parameters.
List * contexts
Linked list of Id3v2ContentContext parsing instructions defining frame field structure.
List * entries
Linked list of Id3v2ContentEntry parsed data fields corresponding to contexts.
List * frames
Linked list of Id3v2Frame structures containing all tag metadata.