comparison sidlib.c @ 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 ee56f1f2b528
children e35e15f07c66
comparison
equal deleted inserted replaced
318:f3ba2ba894b1 319:6d0143e43edf
6 #include "sidlib.h" 6 #include "sidlib.h"
7 #include "th_endian.h" 7 #include "th_endian.h"
8 #include "th_string.h" 8 #include "th_string.h"
9 9
10 10
11 BOOL sidlib_fread_str(th_ioctx *ctx, char **str, const size_t len) 11 static char *sidlib_strdup_convert(SIDLibChConvCtx *chconv, const char *str)
12 {
13 if (chconv != NULL)
14 return chconv->convert(chconv, str);
15 else
16 return th_strdup(str);
17 }
18
19
20 static BOOL sidlib_fread_str(th_ioctx *ctx, SIDLibChConvCtx *chconv, char **str, const size_t len)
12 { 21 {
13 char *tmp; 22 char *tmp;
14 23
15 if ((*str = tmp = th_malloc(len + 1)) == NULL) 24 if ((*str = tmp = th_malloc(len + 1)) == NULL)
16 { 25 {
27 len); 36 len);
28 goto err; 37 goto err;
29 } 38 }
30 39
31 tmp[len] = 0; 40 tmp[len] = 0;
41
42 if (chconv != NULL)
43 {
44 *str = chconv->convert(chconv, tmp);
45 th_free(tmp);
46 }
32 return TRUE; 47 return TRUE;
33 48
34 err: 49 err:
35 th_free(tmp); 50 th_free(tmp);
36 return FALSE; 51 return FALSE;
92 th_free(data); 107 th_free(data);
93 return ret; 108 return ret;
94 } 109 }
95 110
96 111
97 int sidlib_read_sid_file(th_ioctx *ctx, SIDLibPSIDHeader *psid, const BOOL newSLDB) 112 int sidlib_read_sid_file(th_ioctx *ctx, SIDLibPSIDHeader *psid,
113 const BOOL newSLDB, SIDLibChConvCtx *chconv)
98 { 114 {
99 int ret = THERR_OK; 115 int ret = THERR_OK;
100 th_md5state_t state; 116 th_md5state_t state;
101 off_t hdrStart, hdrEnd; 117 off_t hdrStart, hdrEnd;
102 118
129 goto exit; 145 goto exit;
130 } 146 }
131 147
132 psid->isRSID = psid->magic[0] == 'R'; 148 psid->isRSID = psid->magic[0] == 'R';
133 149
134 if (!sidlib_fread_str(ctx, &psid->sidName, SIDLIB_PSID_STR_LEN) || 150 if (!sidlib_fread_str(ctx, chconv, &psid->sidName, SIDLIB_PSID_STR_LEN) ||
135 !sidlib_fread_str(ctx, &psid->sidAuthor, SIDLIB_PSID_STR_LEN) || 151 !sidlib_fread_str(ctx, chconv, &psid->sidAuthor, SIDLIB_PSID_STR_LEN) ||
136 !sidlib_fread_str(ctx, &psid->sidCopyright, SIDLIB_PSID_STR_LEN)) 152 !sidlib_fread_str(ctx, chconv, &psid->sidCopyright, SIDLIB_PSID_STR_LEN))
137 { 153 {
138 ret = th_io_error(ctx, ctx->status, 154 ret = th_io_error(ctx, ctx->status,
139 "Error reading SID file header data."); 155 "Error reading SID file header data.");
140 goto exit; 156 goto exit;
141 } 157 }
216 exit: 232 exit:
217 return ret; 233 return ret;
218 } 234 }
219 235
220 236
221 int sidlib_read_sid_file_alloc(th_ioctx *ctx, SIDLibPSIDHeader **ppsid, const BOOL newSLDB) 237 int sidlib_read_sid_file_alloc(th_ioctx *ctx, SIDLibPSIDHeader **ppsid,
238 const BOOL newSLDB, SIDLibChConvCtx *chconv)
222 { 239 {
223 if ((*ppsid = th_malloc0(sizeof(SIDLibPSIDHeader))) == NULL) 240 if ((*ppsid = th_malloc0(sizeof(SIDLibPSIDHeader))) == NULL)
224 return THERR_MALLOC; 241 return THERR_MALLOC;
225 242
226 (*ppsid)->allocated = TRUE; 243 (*ppsid)->allocated = TRUE;
227 244
228 return sidlib_read_sid_file(ctx, *ppsid, newSLDB); 245 return sidlib_read_sid_file(ctx, *ppsid, newSLDB, chconv);
229 } 246 }
230 247
231 248
232 void sidlib_free_sid_file(SIDLibPSIDHeader *psid) 249 void sidlib_free_sid_file(SIDLibPSIDHeader *psid)
233 { 250 {
600 617
601 618
602 static int sidlib_stildb_entry_realloc( 619 static int sidlib_stildb_entry_realloc(
603 SIDLibSTILNode *node, 620 SIDLibSTILNode *node,
604 const int nsubtune, const BOOL alloc, 621 const int nsubtune, const BOOL alloc,
605 const int nfield, const char *fdata) 622 const int nfield, const char *fdata,
623 SIDLibChConvCtx *chconv)
606 { 624 {
607 SIDLibSTILSubTune *subtune; 625 SIDLibSTILSubTune *subtune;
608 626
609 if (node == NULL) 627 if (node == NULL)
610 return THERR_NULLPTR; 628 return THERR_NULLPTR;
630 SIDLibSTILField *field = &subtune->fields[nfield]; 648 SIDLibSTILField *field = &subtune->fields[nfield];
631 649
632 if ((field->data = th_realloc(field->data, (field->ndata + 1) * sizeof(char *))) == NULL) 650 if ((field->data = th_realloc(field->data, (field->ndata + 1) * sizeof(char *))) == NULL)
633 return THERR_MALLOC; 651 return THERR_MALLOC;
634 652
635 field->data[field->ndata] = th_strdup(fdata); 653 field->data[field->ndata] = sidlib_strdup_convert(chconv, fdata);
636 field->ndata++; 654 field->ndata++;
637 } 655 }
638 656
639 return THERR_OK; 657 return THERR_OK;
640 } 658 }
662 th_free(node); 680 th_free(node);
663 } 681 }
664 } 682 }
665 683
666 684
667 static int sidlib_stildb_node_new(SIDLibSTILNode **pnode, const char *filename) 685 static int sidlib_stildb_node_new(SIDLibSTILNode **pnode, const char *filename,
686 SIDLibChConvCtx *chconv)
668 { 687 {
669 // Allocate memory for new node 688 // Allocate memory for new node
670 SIDLibSTILNode *node; 689 SIDLibSTILNode *node;
671 int res; 690 int res;
672 691
673 if ((node = *pnode = (SIDLibSTILNode *) th_malloc0(sizeof(SIDLibSTILNode))) == NULL) 692 if ((node = *pnode = (SIDLibSTILNode *) th_malloc0(sizeof(SIDLibSTILNode))) == NULL)
674 return THERR_MALLOC; 693 return THERR_MALLOC;
675 694
676 // Allocate filename and initial space for one subtune 695 // Allocate filename and initial space for one subtune
696 // NOTE! Filename is not converted even if chconv != NULL
677 if ((node->filename = th_strdup(filename)) == NULL) 697 if ((node->filename = th_strdup(filename)) == NULL)
678 return THERR_MALLOC; 698 return THERR_MALLOC;
679 699
680 if ((res = sidlib_stildb_entry_realloc(node, 1, FALSE, -1, NULL)) != THERR_OK) 700 if ((res = sidlib_stildb_entry_realloc(node, 1, FALSE, -1, NULL, chconv)) != THERR_OK)
681 { 701 {
682 sidlib_stildb_node_free(node); 702 sidlib_stildb_node_free(node);
683 return res; 703 return res;
684 } 704 }
685 705
772 792
773 793
774 #define VADDCH(ch) if (strPos < SIDLIB_BUFFER_SIZE) { tmpStr[strPos++] = ch; } 794 #define VADDCH(ch) if (strPos < SIDLIB_BUFFER_SIZE) { tmpStr[strPos++] = ch; }
775 795
776 796
777 int sidlib_stildb_read(th_ioctx *fh, SIDLibSTILDB *dbh) 797 int sidlib_stildb_read(th_ioctx *fh, SIDLibSTILDB *dbh, SIDLibChConvCtx *chconv)
778 { 798 {
779 int ret = THERR_OK, field = -1; 799 int ret = THERR_OK, field = -1;
780 SIDLibSTILParserCtx ctx; 800 SIDLibSTILParserCtx ctx;
781 char *tmpStr = NULL, *fieldName = NULL; 801 char *tmpStr = NULL, *fieldName = NULL;
782 size_t strPos; 802 size_t strPos;
891 if (ctx.ch == EOF || th_iscrlf(ctx.ch) || th_isspace(ctx.ch)) 911 if (ctx.ch == EOF || th_iscrlf(ctx.ch) || th_isspace(ctx.ch))
892 { 912 {
893 // A new file / entry, allocate and append 913 // A new file / entry, allocate and append
894 tmpStr[strPos] = 0; 914 tmpStr[strPos] = 0;
895 915
896 if ((ret = sidlib_stildb_node_new(&entry, tmpStr)) != THERR_OK) 916 if ((ret = sidlib_stildb_node_new(&entry, tmpStr, chconv)) != THERR_OK)
897 goto out; 917 goto out;
898 918
899 th_llist_append_node((th_llist_t **) &dbh->nodes, (th_llist_t *) entry); 919 th_llist_append_node((th_llist_t **) &dbh->nodes, (th_llist_t *) entry);
900 920
901 // Default subtune is 0, for "main tune" information 921 // Default subtune is 0, for "main tune" information
1024 1044
1025 if (field >= 0 && subtune >= 0) 1045 if (field >= 0 && subtune >= 0)
1026 { 1046 {
1027 // Supported field, add it 1047 // Supported field, add it
1028 if ((ret = sidlib_stildb_entry_realloc( 1048 if ((ret = sidlib_stildb_entry_realloc(
1029 entry, subtune, TRUE, field, tmpStr)) != THERR_OK) 1049 entry, subtune, TRUE, field, tmpStr, chconv)) != THERR_OK)
1030 { 1050 {
1031 ret = th_io_error(fh, THERR_MALLOC, 1051 ret = th_io_error(fh, THERR_MALLOC,
1032 "Could not allocate memory for field '%s'.", 1052 "Could not allocate memory for field '%s'.",
1033 fieldName); 1053 fieldName);
1034 goto out; 1054 goto out;