Mercurial > hg > sidinfo
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; |