Mercurial > hg > xmms-sid
comparison src/xs_length.c @ 392:b09d74eb71e6
Working on getting STIL and SLDB using completely dynamically allocated
structures. Indentation cleanups, etc.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 31 May 2006 10:02:00 +0000 |
parents | 3c239e4160d5 |
children | f997b79a7251 |
comparison
equal
deleted
inserted
replaced
391:3cc7455360ad | 392:b09d74eb71e6 |
---|---|
27 #include <stdlib.h> | 27 #include <stdlib.h> |
28 #include <ctype.h> | 28 #include <ctype.h> |
29 #include <string.h> | 29 #include <string.h> |
30 | 30 |
31 | 31 |
32 /* Database handling functions | 32 /* Free memory allocated for given SLDB node |
33 */ | 33 */ |
34 static t_xs_sldb_node *xs_sldb_node_new(void) | 34 static void xs_sldb_node_free(t_xs_sldb_node *pNode) |
35 { | |
36 t_xs_sldb_node *pResult; | |
37 | |
38 /* Allocate memory for new node */ | |
39 pResult = (t_xs_sldb_node *) g_malloc0(sizeof(t_xs_sldb_node)); | |
40 if (!pResult) | |
41 return NULL; | |
42 | |
43 return pResult; | |
44 } | |
45 | |
46 | |
47 static void xs_sldb_node_free(t_xs_sldb_node * pNode) | |
48 { | 35 { |
49 if (pNode) { | 36 if (pNode) { |
50 /* Nothing much to do here ... */ | 37 /* Nothing much to do here ... */ |
38 g_free(pNode->sLengths); | |
51 g_free(pNode); | 39 g_free(pNode); |
52 } | 40 } |
53 } | 41 } |
54 | 42 |
55 | 43 |
56 /* Insert given node to db linked list | 44 /* Insert given node to db linked list |
57 */ | 45 */ |
58 static void xs_sldb_node_insert(t_xs_sldb * db, t_xs_sldb_node * pNode) | 46 static void xs_sldb_node_insert(t_xs_sldb *db, t_xs_sldb_node *pNode) |
59 { | 47 { |
60 assert(db); | 48 assert(db); |
61 | 49 |
62 if (db->pNodes) { | 50 if (db->pNodes) { |
63 /* The first node's pPrev points to last node */ | 51 /* The first node's pPrev points to last node */ |
71 LNEXT = NULL; /* But next is NULL! */ | 59 LNEXT = NULL; /* But next is NULL! */ |
72 } | 60 } |
73 } | 61 } |
74 | 62 |
75 | 63 |
76 /* Parses a time-entry in SLDB format | 64 /* Parse a time-entry in SLDB format |
77 */ | 65 */ |
78 static gint xs_sldb_gettime(gchar * pcStr, size_t * piPos) | 66 static gint xs_sldb_gettime(gchar *pcStr, gint *piPos) |
79 { | 67 { |
80 gint iResult, iTemp; | 68 gint iResult, iTemp; |
81 | 69 |
82 /* Check if it starts with a digit */ | 70 /* Check if it starts with a digit */ |
83 if (isdigit(pcStr[*piPos])) { | 71 if (isdigit(pcStr[*piPos])) { |
109 | 97 |
110 return iResult; | 98 return iResult; |
111 } | 99 } |
112 | 100 |
113 | 101 |
102 /* Parse one SLDB definition line, return SLDB node | |
103 */ | |
114 t_xs_sldb_node * xs_sldb_read_entry(gchar *inLine) | 104 t_xs_sldb_node * xs_sldb_read_entry(gchar *inLine) |
115 { | 105 { |
116 size_t linePos, savePos, tmpI, tmpLen; | 106 gint linePos, savePos, i, tmpLen; |
107 gboolean iOK; | |
117 t_xs_sldb_node *tmpNode; | 108 t_xs_sldb_node *tmpNode; |
118 | 109 |
119 /* Allocate new node */ | 110 /* Allocate new node */ |
120 if ((tmpNode = xs_sldb_node_new()) == NULL) { | 111 tmpNode = (t_xs_sldb_node *) g_malloc0(sizeof(t_xs_sldb_node)); |
121 XSERR("Error allocating new node. Fatal error.\n"); | 112 if (!tmpNode) { |
113 xs_error("Error allocating new node. Fatal error.\n"); | |
122 return NULL; | 114 return NULL; |
123 } | 115 } |
124 | 116 |
125 /* Get hash value */ | 117 /* Get hash value */ |
126 #if (XS_MD5HASH_LENGTH != 16) | 118 linePos = 0; |
127 #error Mismatch in hashcode length. Check against xs_md5.h and fix here. | 119 for (i = 0; i < XS_MD5HASH_LENGTH; i++, linePos += 2) { |
128 #endif | 120 sscanf(&inLine[linePos], "%2x", |
129 sscanf(&inLine[0], "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", | 121 (guint *) &(tmpNode->md5Hash[i])); |
130 (guint *) & (tmpNode->md5Hash[0]), (guint *) & (tmpNode->md5Hash[1]), | 122 } |
131 (guint *) & (tmpNode->md5Hash[2]), (guint *) & (tmpNode->md5Hash[3]), | 123 |
132 (guint *) & (tmpNode->md5Hash[4]), (guint *) & (tmpNode->md5Hash[5]), | |
133 (guint *) & (tmpNode->md5Hash[6]), (guint *) & (tmpNode->md5Hash[7]), | |
134 (guint *) & (tmpNode->md5Hash[8]), (guint *) & (tmpNode->md5Hash[9]), | |
135 (guint *) & (tmpNode->md5Hash[10]), (guint *) & (tmpNode->md5Hash[11]), | |
136 (guint *) & (tmpNode->md5Hash[12]), (guint *) & (tmpNode->md5Hash[13]), | |
137 (guint *) & (tmpNode->md5Hash[14]), (guint *) & (tmpNode->md5Hash[15])); | |
138 | |
139 /* Get playtimes */ | 124 /* Get playtimes */ |
140 if (inLine[linePos] != 0) { | 125 if (inLine[linePos] != 0) { |
141 if (inLine[linePos] != '=') { | 126 if (inLine[linePos] != '=') { |
142 XSERR("'=' expected in SongLengthDB file '%s' line #%d, column #%d\n", | 127 xs_error("'=' expected on column #%d.\n", linePos); |
143 dbFilename, lineNum, linePos); | |
144 | |
145 xs_sldb_node_free(tmpNode); | 128 xs_sldb_node_free(tmpNode); |
146 return NULL; | 129 return NULL; |
147 } else { | 130 } else { |
148 /* First playtime is after '=' */ | 131 /* First playtime is after '=' */ |
149 savePos = ++linePos; | 132 savePos = ++linePos; |
158 else | 141 else |
159 iOK = FALSE; | 142 iOK = FALSE; |
160 } | 143 } |
161 | 144 |
162 if (!iOK) { | 145 if (!iOK) { |
163 XSERR("Invalid plaaplaa\n"); | 146 xs_error("Invalid sub-tune length.\n"); |
164 xs_sldb_node_free(tmpNode); | 147 xs_sldb_node_free(tmpNode); |
165 return NULL; | 148 return NULL; |
166 } | 149 } |
167 | 150 |
168 /* Allocate memory for lengths */ | 151 /* Allocate memory for lengths */ |
169 tmpNode->sLengths = (gint *) g_malloc0(tmpNode->nLengths * sizeof(gint)); | 152 tmpNode->sLengths = (gint *) g_malloc0(tmpNode->nLengths * sizeof(gint)); |
170 if (!tmpNode->sLengths) { | 153 if (!tmpNode->sLengths) { |
171 XSERR("Could not allocate memory for SongLengthDB entry.\n"); | 154 xs_error("Could not allocate memory for node.\n"); |
172 xs_sldb_node_free(tmpNode); | 155 xs_sldb_node_free(tmpNode); |
173 return NULL; | 156 return NULL; |
174 } | 157 } |
175 | 158 |
176 /* Read lengths in */ | 159 /* Read lengths in */ |
177 tmpI = 0; linePos = savePos; iOK = TRUE; | 160 i = 0; |
161 linePos = savePos; | |
162 iOK = TRUE; | |
178 while ((linePos < tmpLen) && iOK) { | 163 while ((linePos < tmpLen) && iOK) { |
179 xs_findnext(inLine, &linePos); | 164 xs_findnext(inLine, &linePos); |
180 | 165 |
181 if (tmpI < tmpNode->nLengths) { | 166 if (i < tmpNode->nLengths) { |
182 tmpNode->sLengths[tmpI] = xs_sldb_gettime(inLine, &linePos); | 167 tmpNode->sLengths[i] = xs_sldb_gettime(inLine, &linePos); |
183 tmpI++; | 168 i++; |
184 } else | 169 } else |
185 iOK = FALSE; | 170 iOK = FALSE; |
186 } | 171 } |
187 | 172 |
188 if (!iOK) { | 173 if (!iOK) { |
197 } | 182 } |
198 | 183 |
199 | 184 |
200 /* Read database to memory | 185 /* Read database to memory |
201 */ | 186 */ |
202 gint xs_sldb_read(t_xs_sldb * db, gchar * dbFilename) | 187 gint xs_sldb_read(t_xs_sldb *db, gchar *dbFilename) |
203 { | 188 { |
204 FILE *inFile; | 189 FILE *inFile; |
205 gchar inLine[XS_BUF_SIZE]; | 190 gchar inLine[XS_BUF_SIZE]; |
206 size_t lineNum, linePos; | 191 gint lineNum; |
207 gboolean iOK; | |
208 t_xs_sldb_node *tmpNode; | 192 t_xs_sldb_node *tmpNode; |
209 assert(db); | 193 assert(db); |
210 | 194 |
211 /* Try to open the file */ | 195 /* Try to open the file */ |
212 if ((inFile = fopen(dbFilename, "ra")) == NULL) { | 196 if ((inFile = fopen(dbFilename, "ra")) == NULL) { |
213 XSERR("Could not open SongLengthDB '%s'\n", dbFilename); | 197 xs_error("Could not open SongLengthDB '%s'\n", dbFilename); |
214 return -1; | 198 return -1; |
215 } | 199 } |
216 | 200 |
217 /* Read and parse the data */ | 201 /* Read and parse the data */ |
218 lineNum = 0; | 202 lineNum = 0; |
219 | 203 |
220 while (!feof(inFile)) { | 204 while (!feof(inFile)) { |
205 gint linePos; | |
221 fgets(inLine, XS_BUF_SIZE, inFile); | 206 fgets(inLine, XS_BUF_SIZE, inFile); |
222 inLine[XS_BUF_SIZE - 1] = 0; | 207 inLine[XS_BUF_SIZE - 1] = 0; |
223 linePos = 0; | 208 linePos = 0; |
224 lineNum++; | 209 lineNum++; |
225 | 210 |
226 /* Check if it is datafield */ | 211 /* Check if it is datafield */ |
227 if (isxdigit(inLine[linePos])) { | 212 if (isxdigit(inLine[linePos])) { |
228 size_t tmpI; | |
229 | |
230 /* Check the length of the hash */ | 213 /* Check the length of the hash */ |
231 for (tmpI = 0; isxdigit(inLine[linePos]); linePos++, tmpI++); | 214 gint hashLen; |
232 | 215 for (hashLen = 0; isxdigit(inLine[linePos]); hashLen++, linePos++); |
233 if (tmpI != XS_MD5HASH_LENGTH_CH) { | 216 |
234 XSERR("Invalid hash in SongLengthDB file '%s' line #%d!\n", dbFilename, lineNum); | 217 if (hashLen != XS_MD5HASH_LENGTH_CH) { |
218 xs_error("Invalid MD5-hash in SongLengthDB file '%s' line #%d!\n", | |
219 dbFilename, lineNum); | |
235 } else { | 220 } else { |
236 /* Parse and add node to db */ | 221 /* Parse and add node to db */ |
237 if ((tmpNode = xs_sldb_read_entry(inLine)) != NULL) | 222 if ((tmpNode = xs_sldb_read_entry(inLine)) != NULL) { |
238 xs_sldb_node_insert(db, tmpNode); | 223 xs_sldb_node_insert(db, tmpNode); |
224 } else { | |
225 xs_error("Invalid entry in SongLengthDB file '%s' line #%d!\n", | |
226 dbFilename, lineNum); | |
227 } | |
239 } | 228 } |
240 } else if ((inLine[0] != ';') && (inLine[0] != '[')) { | 229 } else if ((inLine[linePos] != ';') && (inLine[linePos] != '[')) { |
241 XSERR("Invalid line in SongLengthDB file '%s' line #%d\n", dbFilename, lineNum); | 230 xs_error("Invalid line in SongLengthDB file '%s' line #%d\n", |
231 dbFilename, lineNum); | |
242 } | 232 } |
243 | 233 |
244 } | 234 } |
245 | 235 |
246 /* Close the file */ | 236 /* Close the file */ |
255 * negative if testHash1 < testHash2 | 245 * negative if testHash1 < testHash2 |
256 * positive if testHash1 > testHash2 | 246 * positive if testHash1 > testHash2 |
257 */ | 247 */ |
258 static gint xs_sldb_cmphash(t_xs_md5hash testHash1, t_xs_md5hash testHash2) | 248 static gint xs_sldb_cmphash(t_xs_md5hash testHash1, t_xs_md5hash testHash2) |
259 { | 249 { |
260 register gint i, res = 0; | 250 gint i, d; |
261 | 251 |
262 /* Compute difference of hashes */ | 252 /* Compute difference of hashes */ |
263 for (i = 0; (i < XS_MD5HASH_LENGTH) && (!res); i++) | 253 for (i = 0, d = 0; (i < XS_MD5HASH_LENGTH) && !d; i++) |
264 res = (testHash1[i] - testHash2[i]); | 254 d = (testHash1[i] - testHash2[i]); |
265 | 255 |
266 return res; | 256 return d; |
267 } | 257 } |
268 | 258 |
269 | 259 |
270 /* Get node from db index via binary search | 260 /* Get node from db index via binary search |
271 */ | 261 */ |
443 { | 433 { |
444 FILE *inFile; | 434 FILE *inFile; |
445 t_xs_md5state inState; | 435 t_xs_md5state inState; |
446 t_xs_psidv1_header psidH; | 436 t_xs_psidv1_header psidH; |
447 t_xs_psidv2_header psidH2; | 437 t_xs_psidv2_header psidH2; |
448 #ifdef XS_BUF_DYNAMIC | |
449 guint8 *songData; | 438 guint8 *songData; |
450 #else | |
451 guint8 songData[XS_SIDBUF_SIZE]; | |
452 #endif | |
453 guint8 ib8[2], i8; | 439 guint8 ib8[2], i8; |
454 gint iIndex, iRes; | 440 gint iIndex, iRes; |
455 | 441 |
456 /* Try to open the file */ | 442 /* Try to open the file */ |
457 if ((inFile = fopen(pcFilename, "rb")) == NULL) | 443 if ((inFile = fopen(pcFilename, "rb")) == NULL) |
485 psidH2.startPage = fgetc(inFile); | 471 psidH2.startPage = fgetc(inFile); |
486 psidH2.pageLength = fgetc(inFile); | 472 psidH2.pageLength = fgetc(inFile); |
487 psidH2.reserved = xs_rd_be16(inFile); | 473 psidH2.reserved = xs_rd_be16(inFile); |
488 } | 474 } |
489 | 475 |
490 #ifdef XS_BUF_DYNAMIC | |
491 /* Allocate buffer */ | 476 /* Allocate buffer */ |
492 songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE * sizeof(guint8)); | 477 songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE * sizeof(guint8)); |
493 if (!songData) { | 478 if (!songData) { |
494 fclose(inFile); | 479 fclose(inFile); |
495 return -3; | 480 return -3; |
496 } | 481 } |
497 #endif | |
498 | 482 |
499 /* Read data to buffer */ | 483 /* Read data to buffer */ |
500 iRes = fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile); | 484 iRes = fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile); |
501 fclose(inFile); | 485 fclose(inFile); |
502 | 486 |
509 } else { | 493 } else { |
510 /* Append "as is" */ | 494 /* Append "as is" */ |
511 xs_md5_append(&inState, songData, iRes); | 495 xs_md5_append(&inState, songData, iRes); |
512 } | 496 } |
513 | 497 |
514 #ifdef XS_BUF_DYNAMIC | |
515 /* Free buffer */ | 498 /* Free buffer */ |
516 g_free(songData); | 499 g_free(songData); |
517 #endif | |
518 | 500 |
519 /* Append header data to hash */ | 501 /* Append header data to hash */ |
520 #define XSADDHASH(QDATAB) { ib8[0] = (QDATAB & 0xff); ib8[1] = (QDATAB >> 8); xs_md5_append(&inState, (guint8 *) &ib8, sizeof(ib8)); } | 502 #define XSADDHASH(QDATAB) { ib8[0] = (QDATAB & 0xff); ib8[1] = (QDATAB >> 8); xs_md5_append(&inState, (guint8 *) &ib8, sizeof(ib8)); } |
521 | 503 |
522 XSADDHASH(psidH.initAddress) | 504 XSADDHASH(psidH.initAddress) |
551 } | 533 } |
552 | 534 |
553 | 535 |
554 /* Get song lengths | 536 /* Get song lengths |
555 */ | 537 */ |
556 t_xs_sldb_node *xs_sldb_get(t_xs_sldb * db, gchar * pcFilename) | 538 t_xs_sldb_node *xs_sldb_get(t_xs_sldb *db, gchar *pcFilename) |
557 { | 539 { |
558 t_xs_sldb_node *pResult; | 540 t_xs_sldb_node *pResult; |
559 t_xs_md5hash dbHash; | 541 t_xs_md5hash dbHash; |
560 | 542 |
561 /* Get the hash and then look up from db */ | 543 /* Get the hash and then look up from db */ |