changeset 319:6d0143e43edf

Add functionality and API changes for doing on-the-fly character set conversion of STIL data and PSID header string fields while reading them.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 11 Jan 2020 20:12:00 +0200
parents f3ba2ba894b1
children e315bed7d791
files sidinfo.c sidlib.c sidlib.h
diffstat 3 files changed, 55 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/sidinfo.c	Sat Jan 11 19:11:34 2020 +0200
+++ b/sidinfo.c	Sat Jan 11 20:12:00 2020 +0200
@@ -991,7 +991,7 @@
     th_io_set_handlers(inFile, siPSIDError, NULL);
 
     // Read PSID data
-    if ((res = sidlib_read_sid_file_alloc(inFile, &psid, setSLDBNewFormat)) != THERR_OK)
+    if ((res = sidlib_read_sid_file_alloc(inFile, &psid, setSLDBNewFormat, NULL)) != THERR_OK)
         goto error;
 
     // Get songlength information, if any
@@ -1287,7 +1287,7 @@
             goto err2;
         }
 
-        if ((ret = sidlib_stildb_read(inFile, sidSTILDB)) != THERR_OK)
+        if ((ret = sidlib_stildb_read(inFile, sidSTILDB, NULL)) != THERR_OK)
         {
             THERR("Error parsing STIL: %s\n",
                 th_error_str(ret));
--- a/sidlib.c	Sat Jan 11 19:11:34 2020 +0200
+++ b/sidlib.c	Sat Jan 11 20:12:00 2020 +0200
@@ -8,7 +8,16 @@
 #include "th_string.h"
 
 
-BOOL sidlib_fread_str(th_ioctx *ctx, char **str, const size_t len)
+static char *sidlib_strdup_convert(SIDLibChConvCtx *chconv, const char *str)
+{
+    if (chconv != NULL)
+        return chconv->convert(chconv, str);
+    else
+        return th_strdup(str);
+}
+
+
+static BOOL sidlib_fread_str(th_ioctx *ctx, SIDLibChConvCtx *chconv, char **str, const size_t len)
 {
     char *tmp;
 
@@ -29,6 +38,12 @@
     }
 
     tmp[len] = 0;
+
+    if (chconv != NULL)
+    {
+        *str = chconv->convert(chconv, tmp);
+        th_free(tmp);
+    }
     return TRUE;
 
 err:
@@ -94,7 +109,8 @@
 }
 
 
-int sidlib_read_sid_file(th_ioctx *ctx, SIDLibPSIDHeader *psid, const BOOL newSLDB)
+int sidlib_read_sid_file(th_ioctx *ctx, SIDLibPSIDHeader *psid,
+    const BOOL newSLDB, SIDLibChConvCtx *chconv)
 {
     int ret = THERR_OK;
     th_md5state_t state;
@@ -131,9 +147,9 @@
 
     psid->isRSID = psid->magic[0] == 'R';
 
-    if (!sidlib_fread_str(ctx, &psid->sidName, SIDLIB_PSID_STR_LEN) ||
-        !sidlib_fread_str(ctx, &psid->sidAuthor, SIDLIB_PSID_STR_LEN) ||
-        !sidlib_fread_str(ctx, &psid->sidCopyright, SIDLIB_PSID_STR_LEN))
+    if (!sidlib_fread_str(ctx, chconv, &psid->sidName, SIDLIB_PSID_STR_LEN) ||
+        !sidlib_fread_str(ctx, chconv, &psid->sidAuthor, SIDLIB_PSID_STR_LEN) ||
+        !sidlib_fread_str(ctx, chconv, &psid->sidCopyright, SIDLIB_PSID_STR_LEN))
     {
         ret = th_io_error(ctx, ctx->status,
             "Error reading SID file header data.");
@@ -218,14 +234,15 @@
 }
 
 
-int sidlib_read_sid_file_alloc(th_ioctx *ctx, SIDLibPSIDHeader **ppsid, const BOOL newSLDB)
+int sidlib_read_sid_file_alloc(th_ioctx *ctx, SIDLibPSIDHeader **ppsid,
+    const BOOL newSLDB, SIDLibChConvCtx *chconv)
 {
     if ((*ppsid = th_malloc0(sizeof(SIDLibPSIDHeader))) == NULL)
         return THERR_MALLOC;
 
     (*ppsid)->allocated = TRUE;
 
-    return sidlib_read_sid_file(ctx, *ppsid, newSLDB);
+    return sidlib_read_sid_file(ctx, *ppsid, newSLDB, chconv);
 }
 
 
@@ -602,7 +619,8 @@
 static int sidlib_stildb_entry_realloc(
     SIDLibSTILNode *node,
     const int nsubtune, const BOOL alloc,
-    const int nfield, const char *fdata)
+    const int nfield, const char *fdata,
+    SIDLibChConvCtx *chconv)
 {
     SIDLibSTILSubTune *subtune;
 
@@ -632,7 +650,7 @@
         if ((field->data = th_realloc(field->data, (field->ndata + 1) * sizeof(char *))) == NULL)
             return THERR_MALLOC;
 
-        field->data[field->ndata] = th_strdup(fdata);
+        field->data[field->ndata] = sidlib_strdup_convert(chconv, fdata);
         field->ndata++;
     }
 
@@ -664,7 +682,8 @@
 }
 
 
-static int sidlib_stildb_node_new(SIDLibSTILNode **pnode, const char *filename)
+static int sidlib_stildb_node_new(SIDLibSTILNode **pnode, const char *filename,
+    SIDLibChConvCtx *chconv)
 {
     // Allocate memory for new node
     SIDLibSTILNode *node;
@@ -674,10 +693,11 @@
         return THERR_MALLOC;
 
     // Allocate filename and initial space for one subtune
+    // NOTE! Filename is not converted even if chconv != NULL
     if ((node->filename = th_strdup(filename)) == NULL)
         return THERR_MALLOC;
 
-    if ((res = sidlib_stildb_entry_realloc(node, 1, FALSE, -1, NULL)) != THERR_OK)
+    if ((res = sidlib_stildb_entry_realloc(node, 1, FALSE, -1, NULL, chconv)) != THERR_OK)
     {
         sidlib_stildb_node_free(node);
         return res;
@@ -774,7 +794,7 @@
 #define VADDCH(ch) if (strPos < SIDLIB_BUFFER_SIZE) { tmpStr[strPos++] = ch; }
 
 
-int sidlib_stildb_read(th_ioctx *fh, SIDLibSTILDB *dbh)
+int sidlib_stildb_read(th_ioctx *fh, SIDLibSTILDB *dbh, SIDLibChConvCtx *chconv)
 {
     int ret = THERR_OK, field = -1;
     SIDLibSTILParserCtx ctx;
@@ -893,7 +913,7 @@
                 // A new file / entry, allocate and append
                 tmpStr[strPos] = 0;
 
-                if ((ret = sidlib_stildb_node_new(&entry, tmpStr)) != THERR_OK)
+                if ((ret = sidlib_stildb_node_new(&entry, tmpStr, chconv)) != THERR_OK)
                     goto out;
 
                 th_llist_append_node((th_llist_t **) &dbh->nodes, (th_llist_t *) entry);
@@ -1026,7 +1046,7 @@
                 {
                     // Supported field, add it
                     if ((ret = sidlib_stildb_entry_realloc(
-                        entry, subtune, TRUE, field, tmpStr)) != THERR_OK)
+                        entry, subtune, TRUE, field, tmpStr, chconv)) != THERR_OK)
                     {
                         ret = th_io_error(fh, THERR_MALLOC,
                             "Could not allocate memory for field '%s'.",
--- a/sidlib.h	Sat Jan 11 19:11:34 2020 +0200
+++ b/sidlib.h	Sat Jan 11 20:12:00 2020 +0200
@@ -84,7 +84,7 @@
 typedef struct
 {
     int ndata;
-    char **data;
+    char **data;  // Converted through SIDLibChConvCtx if conversion is used
 } SIDLibSTILField;
 
 
@@ -99,9 +99,11 @@
 {
     th_llist_t node;
 
-    char *filename; // HVSC path/filename
+    char *filename;    // HVSC path/filename (NOT converted through SIDLibChConvCtx)
     size_t nsubtunes;  // Number of subtune information structures
-    SIDLibSTILSubTune *subtunes;
+    SIDLibSTILSubTune *subtunes; // NOTE! Subtunes are in undefined order here
+        // (through with correct SIDLibSTILSubTune::tune number, of course)
+        // unless sidlib_stildb_build_index() has been run on the SIDLibSTILDB
 
     // Internal use only
     SIDLibSLDBNode *lengths;
@@ -127,8 +129,9 @@
         nSongs,          // Number of subsongs
         startSong;       // Default starting song
     uint32_t speed;      // Speed
+
     char *sidName;       // Descriptive text-fields, ASCIIZ
-    char *sidAuthor;
+    char *sidAuthor;     // Converted through SIDLibChConvCtx if conversion is used
     char *sidCopyright;
 
     // PSIDv2+ data
@@ -148,16 +151,24 @@
 } SIDLibPSIDHeader;
 
 
+typedef struct SIDLibChConvCtx
+{
+    void *data;
+    char* (*convert)(struct SIDLibChConvCtx *ctx, const char *str);
+} SIDLibChConvCtx;
+
+
 //
 // Globals
 //
-const char *sidlib_stil_fields[STF_LAST];
+const char *     sidlib_stil_fields[STF_LAST];
+
 
 //
 // Functions
 //
-int              sidlib_read_sid_file(th_ioctx *ctx, SIDLibPSIDHeader *psid, const BOOL newSLDB);
-int              sidlib_read_sid_file_alloc(th_ioctx *ctx, SIDLibPSIDHeader **ppsid, const BOOL newSLDB);
+int              sidlib_read_sid_file(th_ioctx *ctx, SIDLibPSIDHeader *psid, const BOOL newSLDB, SIDLibChConvCtx *chconv);
+int              sidlib_read_sid_file_alloc(th_ioctx *ctx, SIDLibPSIDHeader **ppsid, const BOOL newSLDB, SIDLibChConvCtx *chconv);
 void             sidlib_free_sid_file(SIDLibPSIDHeader *psid);
 
 const char *     sidlib_get_sid_clock_str(const int flags);
@@ -170,7 +181,7 @@
 SIDLibSLDBNode * sidlib_sldb_get_by_hash(SIDLibSLDB *dbh, th_md5hash_t hash);
 
 int              sidlib_stildb_new(SIDLibSTILDB **pdbh);
-int              sidlib_stildb_read(th_ioctx *ctx, SIDLibSTILDB *dbh);
+int              sidlib_stildb_read(th_ioctx *ctx, SIDLibSTILDB *dbh, SIDLibChConvCtx *chconv);
 int              sidlib_stildb_build_index(SIDLibSTILDB *dbh);
 void             sidlib_stildb_free(SIDLibSTILDB *dbh);
 SIDLibSTILNode * sidlib_stildb_get_node(SIDLibSTILDB *dbh, const char *filename);