Coverage Report

Created: 2026-06-30 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libsndfile/src/strings.c
Line
Count
Source
1
/*
2
** Copyright (C) 2001-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
3
**
4
** This program is free software; you can redistribute it and/or modify
5
** it under the terms of the GNU Lesser General Public License as published by
6
** the Free Software Foundation; either version 2.1 of the License, or
7
** (at your option) any later version.
8
**
9
** This program is distributed in the hope that it will be useful,
10
** but WITHOUT ANY WARRANTY; without even the implied warranty of
11
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
** GNU Lesser General Public License for more details.
13
**
14
** You should have received a copy of the GNU Lesser General Public License
15
** along with this program; if not, write to the Free Software
16
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
*/
18
19
#include  "sfconfig.h"
20
21
#include  <stdio.h>
22
#include  <string.h>
23
#include  <math.h>
24
25
#include  "sndfile.h"
26
#include  "common.h"
27
28
#define STRINGS_DEBUG 0
29
30
int
31
psf_store_string (SF_PRIVATE *psf, int str_type, const char *str)
32
25.4k
{ char  new_str [128] ;
33
25.4k
  size_t  str_len ;
34
25.4k
  int   k, str_flags ;
35
36
25.4k
  if (str == NULL)
37
0
    return SFE_STR_BAD_STRING ;
38
39
25.4k
  str_len = strlen (str) ;
40
41
  /* A few extra checks for write mode. */
42
25.4k
  if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
43
0
  { if ((psf->strings.flags & SF_STR_ALLOW_START) == 0)
44
0
      return SFE_STR_NO_SUPPORT ;
45
0
    if (psf->have_written && (psf->strings.flags & SF_STR_ALLOW_END) == 0)
46
0
      return SFE_STR_NO_SUPPORT ;
47
    /* Only allow zero length strings for software. */
48
0
    if (str_type != SF_STR_SOFTWARE && str_len == 0)
49
0
      return SFE_STR_BAD_STRING ;
50
25.4k
    } ;
51
52
  /* Find the next free slot in table. */
53
759k
  for (k = 0 ; k < SF_MAX_STRINGS ; k++)
54
737k
  { /* If we find a matching entry clear it. */
55
737k
    if (psf->strings.data [k].type == str_type)
56
3.21k
      psf->strings.data [k].type = -1 ;
57
58
737k
    if (psf->strings.data [k].type == 0)
59
3.90k
      break ;
60
737k
    } ;
61
62
  /* Determine flags */
63
25.4k
  str_flags = SF_STR_LOCATE_START ;
64
25.4k
  if (psf->file.mode == SFM_RDWR || psf->have_written)
65
0
  { if ((psf->strings.flags & SF_STR_ALLOW_END) == 0)
66
0
      return SFE_STR_NO_ADD_END ;
67
0
    str_flags = SF_STR_LOCATE_END ;
68
25.4k
    } ;
69
70
  /* More sanity checking. */
71
25.4k
  if (k >= SF_MAX_STRINGS)
72
21.5k
    return SFE_STR_MAX_COUNT ;
73
74
3.90k
  if (k == 0 && psf->strings.storage_used != 0)
75
0
  { psf_log_printf (psf, "SFE_STR_WEIRD : k == 0 && psf->strings.storage_used != 0\n") ;
76
0
    return SFE_STR_WEIRD ;
77
3.90k
    } ;
78
79
3.90k
  if (k != 0 && psf->strings.storage_used == 0)
80
0
  { psf_log_printf (psf, "SFE_STR_WEIRD : k != 0 && psf->strings.storage_used == 0\n") ;
81
0
    return SFE_STR_WEIRD ;
82
3.90k
    } ;
83
84
  /* Special case for the first string. */
85
3.90k
  if (k == 0)
86
514
    psf->strings.storage_used = 0 ;
87
88
3.90k
  switch (str_type)
89
3.90k
  { case SF_STR_SOFTWARE :
90
        /* In write mode, want to append libsndfile-version to string. */
91
1.00k
        if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
92
0
        { if (strstr (str, PACKAGE_NAME) == NULL)
93
0
          { /*
94
            ** If the supplied string does not already contain a
95
            ** libsndfile-X.Y.Z component, then add it.
96
            */
97
0
            if (strlen (str) == 0)
98
0
              snprintf (new_str, sizeof (new_str), "%s-%s", PACKAGE_NAME, PACKAGE_VERSION) ;
99
0
            else
100
0
              snprintf (new_str, sizeof (new_str), "%s (%s-%s)", str, PACKAGE_NAME, PACKAGE_VERSION) ;
101
0
            }
102
0
          else
103
0
            snprintf (new_str, sizeof (new_str), "%s", str) ;
104
105
0
          str = new_str ;
106
0
          } ;
107
1.00k
        break ;
108
109
601
    case SF_STR_TITLE :
110
993
    case SF_STR_COPYRIGHT :
111
1.36k
    case SF_STR_ARTIST :
112
1.79k
    case SF_STR_COMMENT :
113
2.04k
    case SF_STR_DATE :
114
2.30k
    case SF_STR_ALBUM :
115
2.40k
    case SF_STR_LICENSE :
116
2.65k
    case SF_STR_TRACKNUMBER :
117
2.90k
    case SF_STR_GENRE :
118
2.90k
        break ;
119
120
0
    default :
121
0
      psf_log_printf (psf, "%s : SFE_STR_BAD_TYPE\n", __func__) ;
122
0
      return SFE_STR_BAD_TYPE ;
123
3.90k
    } ;
124
125
  /* Plus one to catch string terminator. */
126
3.90k
  str_len = strlen (str) + 1 ;
127
128
3.90k
  if (psf->strings.storage_used + str_len + 1 > psf->strings.storage_len)
129
526
  { char * temp = psf->strings.storage ;
130
526
    size_t newlen = 2 * psf->strings.storage_len + str_len + 1 ;
131
132
526
    newlen = newlen < 256 ? 256 : newlen ;
133
134
526
    char * new_storage = realloc(temp, newlen);
135
526
    if (new_storage == NULL)
136
0
    {
137
0
      return SFE_MALLOC_FAILED ;
138
526
      } else {
139
526
      psf->strings.storage = new_storage;
140
526
      } ;
141
142
526
    psf->strings.storage_len = newlen ;
143
3.90k
    } ;
144
145
3.90k
  psf->strings.data [k].type = str_type ;
146
3.90k
  psf->strings.data [k].offset = psf->strings.storage_used ;
147
3.90k
  psf->strings.data [k].flags = str_flags ;
148
149
3.90k
  memcpy (psf->strings.storage + psf->strings.storage_used, str, str_len) ;
150
3.90k
  psf->strings.storage_used += str_len ;
151
152
3.90k
  psf->strings.flags |= str_flags ;
153
154
#if STRINGS_DEBUG
155
  printf ("storage_used         : %zd / %zd\n", psf->strings.storage_used, psf->strings.storage_len) ;
156
  psf_hexdump (psf->strings.storage, psf->strings.storage_used) ;
157
#endif
158
159
3.90k
  return 0 ;
160
3.90k
} /* psf_store_string */
161
162
int
163
psf_set_string (SF_PRIVATE *psf, int str_type, const char *str)
164
0
{ if (psf->file.mode == SFM_READ)
165
0
    return SFE_STR_NOT_WRITE ;
166
167
0
  return psf_store_string (psf, str_type, str) ;
168
0
} /* psf_set_string */
169
170
const char*
171
psf_get_string (SF_PRIVATE *psf, int str_type)
172
0
{ int k ;
173
174
0
  for (k = 0 ; k < SF_MAX_STRINGS ; k++)
175
0
    if (str_type == psf->strings.data [k].type)
176
0
      return psf->strings.storage + psf->strings.data [k].offset ;
177
178
0
  return NULL ;
179
0
} /* psf_get_string */
180
181
int
182
psf_location_string_count (const SF_PRIVATE * psf, int location)
183
0
{ int k, count = 0 ;
184
185
0
  for (k = 0 ; k < SF_MAX_STRINGS ; k++)
186
0
    if (psf->strings.data [k].type > 0 && psf->strings.data [k].flags & location)
187
0
      count ++ ;
188
189
0
  return count ;
190
0
} /* psf_location_string_count */