Mercurial > audlegacy-plugins
view src/sid/xs_stil.c @ 3148:d443c917dab9
Remove stale library variable from Makefile, as pointed out by RafaŠČ MuŤ÷yŠČo on #audacious.
author | Tony Vroon <chainsaw@gentoo.org> |
---|---|
date | Mon, 11 May 2009 17:32:04 +0100 |
parents | 09879415c666 |
children |
line wrap: on
line source
/* XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS) STIL-database handling functions Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org> (C) Copyright 1999-2007 Tecnic Software productions (TNSP) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "xs_stil.h" #include "xs_support.h" #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <stdarg.h> /* Database handling functions */ static gboolean xs_stildb_node_realloc(stil_node_t *node, gint nsubTunes) { if (!node) return FALSE; /* Re-allocate subTune structure if needed */ if (nsubTunes > node->nsubTunes) { gint clearIndex, clearLength; node->subTunes = (stil_subnode_t **) g_realloc(node->subTunes, (nsubTunes + 1) * sizeof(stil_subnode_t **)); if (!node->subTunes) { xs_error("SubTune pointer structure realloc failed.\n"); return FALSE; } /* Clear the newly allocated memory */ if (node->nsubTunes == 0) { clearIndex = 0; clearLength = nsubTunes + 1; } else { clearIndex = node->nsubTunes + 1; clearLength = (nsubTunes - clearIndex + 1); } memset(&(node->subTunes[clearIndex]), 0, clearLength * sizeof(stil_subnode_t **)); node->nsubTunes = nsubTunes; } /* Allocate memory for subTune */ if (!node->subTunes[nsubTunes]) { node->subTunes[nsubTunes] = (stil_subnode_t *) g_malloc0(sizeof(stil_subnode_t)); if (!node->subTunes[nsubTunes]) { xs_error("SubTune structure malloc failed!\n"); return FALSE; } } return TRUE; } static void xs_stildb_node_free(stil_node_t *node) { gint i; stil_subnode_t *subnode; if (!node) return; /* Free subtune information */ for (i = 0; i <= node->nsubTunes; i++) { subnode = node->subTunes[i]; if (subnode) { g_free(subnode->name); g_free(subnode->author); g_free(subnode->info); g_free(subnode->title); g_free(subnode); } } g_free(node->subTunes); g_free(node->filename); g_free(node); } static stil_node_t *xs_stildb_node_new(gchar *filename) { stil_node_t *result; /* Allocate memory for new node */ result = (stil_node_t *) g_malloc0(sizeof(stil_node_t)); if (!result) return NULL; /* Allocate filename and initial space for one subtune */ result->filename = g_strdup(filename); if (!result->filename || !xs_stildb_node_realloc(result, 1)) { xs_stildb_node_free(result); return NULL; } return result; } /* Insert given node to db linked list */ static void xs_stildb_node_insert(xs_stildb_t *db, stil_node_t *node) { assert(db != NULL); if (db->nodes) { /* The first node's pPrev points to last node */ LPREV = db->nodes->prev; /* New node's prev = Previous last node */ db->nodes->prev->next = node; /* Previous last node's next = New node */ db->nodes->prev = node; /* New last node = New node */ LNEXT = NULL; /* But next is NULL! */ } else { db->nodes = node; /* First node ... */ LPREV = node; /* ... it's also last */ LNEXT = NULL; /* But next is NULL! */ } } /* Read database (additively) to given db-structure */ #define XS_STILDB_MULTI \ if (isMulti) { \ isMulti = FALSE; \ xs_pstrcat(&(tmnode->subTunes[subEntry]->info), "\n");\ } static void XS_STILDB_ERR(gint lineNum, gchar *inLine, const char *fmt, ...) { va_list ap; va_start(ap, fmt); xs_error(fmt, ap); va_end(ap); fprintf(stderr, "#%d: '%s'\n", lineNum, inLine); } gint xs_stildb_read(xs_stildb_t *db, gchar *dbFilename) { FILE *inFile; gchar inLine[XS_BUF_SIZE + 16]; /* Since we add some chars here and there */ size_t lineNum; stil_node_t *tmnode; gboolean isError, isMulti; gint subEntry; gchar *tmpLine = inLine; assert(db != NULL); /* Try to open the file */ if ((inFile = fopen(dbFilename, "ra")) == NULL) { xs_error("Could not open STILDB '%s'\n", dbFilename); return -1; } /* Read and parse the data */ lineNum = 0; isError = FALSE; isMulti = FALSE; tmnode = NULL; subEntry = 0; while (!isError && fgets(inLine, XS_BUF_SIZE, inFile) != NULL) { size_t linePos = 0, eolPos = 0; xs_findeol(inLine, &eolPos); inLine[eolPos] = 0; lineNum++; tmpLine = XS_CS_STIL(inLine); switch (tmpLine[0]) { case '/': /* Check if we are already parsing entry */ isMulti = FALSE; if (tmnode) { XS_STILDB_ERR(lineNum, tmpLine, "New entry found before end of current ('%s')!\n", tmnode->filename); xs_stildb_node_free(tmnode); } /* A new node */ subEntry = 0; tmnode = xs_stildb_node_new(tmpLine); if (!tmnode) { /* Allocation failed */ XS_STILDB_ERR(lineNum, tmpLine, "Could not allocate new STILdb-node!\n"); isError = TRUE; } break; case '(': /* A new sub-entry */ isMulti = FALSE; linePos++; if (tmpLine[linePos] == '#') { linePos++; if (isdigit(tmpLine[linePos])) { size_t savePos = linePos; xs_findnum(tmpLine, &linePos); tmpLine[linePos] = 0; subEntry = atol(&tmpLine[savePos]); /* Sanity check */ if (subEntry < 1) { XS_STILDB_ERR(lineNum, tmpLine, "Number of subEntry (%i) for '%s' is invalid\n", subEntry, tmnode ? tmnode->filename : ""); subEntry = 0; } } else { XS_STILDB_ERR(lineNum, tmpLine, "Syntax error, expected subEntry number.\n"); subEntry = 0; } } else { XS_STILDB_ERR(lineNum, tmpLine, "Syntax error, expected '#' before subEntry number.\n"); subEntry = 0; } break; case 0: case '#': case '\n': case '\r': /* End of entry/field */ isMulti = FALSE; if (tmnode) { /* Insert to database */ xs_stildb_node_insert(db, tmnode); tmnode = NULL; } break; default: /* Check if we are parsing an entry */ xs_findnext(tmpLine, &linePos); if (!tmnode) { XS_STILDB_ERR(lineNum, tmpLine, "Entry data encountered outside of entry or syntax error!\n"); break; } if (!xs_stildb_node_realloc(tmnode, subEntry)) { XS_STILDB_ERR(lineNum, tmpLine, "Could not (re)allocate memory for subEntries!\n"); isError = TRUE; break; } /* Some other type */ if (strncmp(tmpLine, " NAME:", 8) == 0) { XS_STILDB_MULTI; g_free(tmnode->subTunes[subEntry]->name); tmnode->subTunes[subEntry]->name = g_strdup(&tmpLine[9]); } else if (strncmp(tmpLine, " TITLE:", 8) == 0) { XS_STILDB_MULTI; isMulti = TRUE; if (!tmnode->subTunes[subEntry]->title) tmnode->subTunes[subEntry]->title = g_strdup(&tmpLine[9]); xs_pstrcat(&(tmnode->subTunes[subEntry]->info), &tmpLine[2]); } else if (strncmp(tmpLine, " AUTHOR:", 8) == 0) { XS_STILDB_MULTI; g_free(tmnode->subTunes[subEntry]->author); tmnode->subTunes[subEntry]->author = g_strdup(&tmpLine[9]); } else if (strncmp(tmpLine, " ARTIST:", 8) == 0) { XS_STILDB_MULTI; isMulti = TRUE; xs_pstrcat(&(tmnode->subTunes[subEntry]->info), &tmpLine[1]); } else if (strncmp(tmpLine, "COMMENT:", 8) == 0) { XS_STILDB_MULTI; isMulti = TRUE; xs_pstrcat(&(tmnode->subTunes[subEntry]->info), tmpLine); } else { if (isMulti) { xs_pstrcat(&(tmnode->subTunes[subEntry]->info), " "); xs_pstrcat(&(tmnode->subTunes[subEntry]->info), &tmpLine[linePos]); } else { XS_STILDB_ERR(lineNum, tmpLine, "Entry continuation found when isMulti == FALSE.\n"); } } break; } XS_CS_FREE(tmpLine); } /* while */ /* Check if there is one remaining node */ if (tmnode) xs_stildb_node_insert(db, tmnode); /* Close the file */ fclose(inFile); return 0; } /* Compare two nodes */ static gint xs_stildb_cmp(const void *node1, const void *node2) { /* We assume here that we never ever get NULL-pointers or similar */ return strcmp( (*(stil_node_t **) node1)->filename, (*(stil_node_t **) node2)->filename); } /* (Re)create index */ gint xs_stildb_index(xs_stildb_t *db) { stil_node_t *curr; size_t i; /* Free old index */ if (db->pindex) { g_free(db->pindex); db->pindex = NULL; } /* Get size of db */ curr = db->nodes; db->n = 0; while (curr) { db->n++; curr = curr->next; } /* Check number of nodes */ if (db->n > 0) { /* Allocate memory for index-table */ db->pindex = (stil_node_t **) g_malloc(sizeof(stil_node_t *) * db->n); if (!db->pindex) return -1; /* Get node-pointers to table */ i = 0; curr = db->nodes; while (curr && (i < db->n)) { db->pindex[i++] = curr; curr = curr->next; } /* Sort the indexes */ qsort(db->pindex, db->n, sizeof(stil_node_t *), xs_stildb_cmp); } return 0; } /* Free a given STIL database */ void xs_stildb_free(xs_stildb_t *db) { stil_node_t *curr, *next; if (!db) return; /* Free the memory allocated for nodes */ curr = db->nodes; while (curr) { next = curr->next; xs_stildb_node_free(curr); curr = next; } db->nodes = NULL; /* Free memory allocated for index */ if (db->pindex) { g_free(db->pindex); db->pindex = NULL; } /* Free structure */ db->n = 0; g_free(db); } /* Get STIL information node from database */ stil_node_t *xs_stildb_get_node(xs_stildb_t *db, gchar *filename) { stil_node_t keyItem, *key, **item; /* Check the database pointers */ if (!db || !db->nodes || !db->pindex) return NULL; /* Look-up index using binary search */ keyItem.filename = filename; key = &keyItem; item = bsearch(&key, db->pindex, db->n, sizeof(stil_node_t *), xs_stildb_cmp); if (item) return *item; else return NULL; }