Coverage Report

Created: 2026-05-16 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libsndfile/src/caf.c
Line
Count
Source
1
/*
2
** Copyright (C) 2005-2017 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  <stdlib.h>
23
#include  <string.h>
24
#include  <ctype.h>
25
#include  <math.h>
26
#include  <inttypes.h>
27
28
#include  "sndfile.h"
29
#include  "sfendian.h"
30
#include  "common.h"
31
#include  "chanmap.h"
32
33
/*------------------------------------------------------------------------------
34
** Macros to handle big/little endian issues.
35
*/
36
37
#define aac_MARKER    MAKE_MARKER ('a', 'a', 'c', ' ')
38
2.46k
#define alac_MARKER   MAKE_MARKER ('a', 'l', 'a', 'c')
39
493
#define alaw_MARKER   MAKE_MARKER ('a', 'l', 'a', 'w')
40
4.45k
#define caff_MARKER   MAKE_MARKER ('c', 'a', 'f', 'f')
41
4.37k
#define chan_MARKER   MAKE_MARKER ('c', 'h', 'a', 'n')
42
24.1k
#define data_MARKER   MAKE_MARKER ('d', 'a', 't', 'a')
43
4.45k
#define desc_MARKER   MAKE_MARKER ('d', 'e', 's', 'c')
44
#define edct_MARKER   MAKE_MARKER ('e', 'd', 'c', 't')
45
168
#define free_MARKER   MAKE_MARKER ('f', 'r', 'e', 'e')
46
#define ima4_MARKER   MAKE_MARKER ('i', 'm', 'a', '4')
47
2.31k
#define info_MARKER   MAKE_MARKER ('i', 'n', 'f', 'o')
48
#define inst_MARKER   MAKE_MARKER ('i', 'n', 's', 't')
49
2.94k
#define kuki_MARKER   MAKE_MARKER ('k', 'u', 'k', 'i')
50
1.00k
#define lpcm_MARKER   MAKE_MARKER ('l', 'p', 'c', 'm')
51
#define mark_MARKER   MAKE_MARKER ('m', 'a', 'r', 'k')
52
#define midi_MARKER   MAKE_MARKER ('m', 'i', 'd', 'i')
53
#define mp1_MARKER    MAKE_MARKER ('.', 'm', 'p', '1')
54
#define mp2_MARKER    MAKE_MARKER ('.', 'm', 'p', '2')
55
#define mp3_MARKER    MAKE_MARKER ('.', 'm', 'p', '3')
56
#define ovvw_MARKER   MAKE_MARKER ('o', 'v', 'v', 'w')
57
5.27k
#define pakt_MARKER   MAKE_MARKER ('p', 'a', 'k', 't')
58
362
#define peak_MARKER   MAKE_MARKER ('p', 'e', 'a', 'k')
59
#define regn_MARKER   MAKE_MARKER ('r', 'e', 'g', 'n')
60
#define strg_MARKER   MAKE_MARKER ('s', 't', 'r', 'g')
61
#define umid_MARKER   MAKE_MARKER ('u', 'm', 'i', 'd')
62
#define uuid_MARKER   MAKE_MARKER ('u', 'u', 'i', 'd')
63
491
#define ulaw_MARKER   MAKE_MARKER ('u', 'l', 'a', 'w')
64
#define MAC3_MARKER   MAKE_MARKER ('M', 'A', 'C', '3')
65
#define MAC6_MARKER   MAKE_MARKER ('M', 'A', 'C', '6')
66
67
368
#define CAF_PEAK_CHUNK_SIZE(ch)   ((int) (sizeof (int) + ch * (sizeof (float) + 8)))
68
69
/*------------------------------------------------------------------------------
70
** Typedefs.
71
*/
72
73
typedef struct
74
{ uint8_t   srate [8] ;
75
  uint32_t  fmt_id ;
76
  uint32_t  fmt_flags ;
77
  uint32_t  pkt_bytes ;
78
  uint32_t  frames_per_packet ;
79
  uint32_t  channels_per_frame ;
80
  uint32_t  bits_per_chan ;
81
} DESC_CHUNK ;
82
83
typedef struct
84
{ int     chanmap_tag ;
85
86
  ALAC_DECODER_INFO alac ;
87
} CAF_PRIVATE ;
88
89
/*------------------------------------------------------------------------------
90
** Private static functions.
91
*/
92
93
static int  caf_close (SF_PRIVATE *psf) ;
94
static int  caf_read_header (SF_PRIVATE *psf) ;
95
static int  caf_write_header (SF_PRIVATE *psf, int calc_length) ;
96
static int  caf_write_tailer (SF_PRIVATE *psf) ;
97
static int  caf_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
98
static int  caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size) ;
99
static int  caf_read_strings (SF_PRIVATE * psf, sf_count_t chunk_size) ;
100
static void caf_write_strings (SF_PRIVATE * psf, int location) ;
101
102
103
static int caf_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info) ;
104
static SF_CHUNK_ITERATOR * caf_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator) ;
105
static int caf_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
106
static int caf_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
107
108
/*------------------------------------------------------------------------------
109
** Public function.
110
*/
111
112
int
113
caf_open (SF_PRIVATE *psf)
114
4.45k
{ CAF_PRIVATE * pcaf ;
115
4.45k
  int subformat, format, error = 0 ;
116
117
4.45k
  if ((psf->container_data = calloc (1, sizeof (CAF_PRIVATE))) == NULL)
118
0
    return SFE_MALLOC_FAILED ;
119
120
4.45k
  pcaf = psf->container_data ;
121
122
4.45k
  if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
123
4.45k
  { if ((error = caf_read_header (psf)))
124
2.48k
      return error ;
125
126
1.97k
    psf->next_chunk_iterator = caf_next_chunk_iterator ;
127
1.97k
    psf->get_chunk_size = caf_get_chunk_size ;
128
1.97k
    psf->get_chunk_data = caf_get_chunk_data ;
129
1.97k
    } ;
130
131
1.97k
  subformat = SF_CODEC (psf->sf.format) ;
132
133
1.97k
  if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
134
0
  { if (psf->is_pipe)
135
0
      return SFE_NO_PIPE_WRITE ;
136
137
0
    format = SF_CONTAINER (psf->sf.format) ;
138
0
    if (format != SF_FORMAT_CAF)
139
0
      return  SFE_BAD_OPEN_FORMAT ;
140
141
0
    psf->blockwidth = psf->bytewidth * psf->sf.channels ;
142
143
0
    if (psf->file.mode != SFM_RDWR || psf->filelength < 44)
144
0
    { psf->filelength = 0 ;
145
0
      psf->datalength = 0 ;
146
0
      psf->dataoffset = 0 ;
147
0
      psf->sf.frames = 0 ;
148
0
      } ;
149
150
0
    psf->strings.flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ;
151
152
    /*
153
    **  By default, add the peak chunk to floating point files. Default behaviour
154
    **  can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE).
155
    */
156
0
    if (psf->file.mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE))
157
0
    { if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
158
0
        return SFE_MALLOC_FAILED ;
159
0
      psf->peak_info->peak_loc = SF_PEAK_START ;
160
0
      } ;
161
162
0
    if ((error = caf_write_header (psf, SF_FALSE)) != 0)
163
0
      return error ;
164
165
0
    psf->write_header = caf_write_header ;
166
0
    psf->set_chunk    = caf_set_chunk ;
167
1.97k
    } ;
168
169
1.97k
  psf->container_close = caf_close ;
170
1.97k
  psf->command = caf_command ;
171
172
1.97k
  switch (subformat)
173
1.97k
  { case SF_FORMAT_PCM_S8 :
174
4
    case SF_FORMAT_PCM_16 :
175
6
    case SF_FORMAT_PCM_24 :
176
8
    case SF_FORMAT_PCM_32 :
177
8
          error = pcm_init (psf) ;
178
8
          break ;
179
180
2
    case SF_FORMAT_ULAW :
181
2
          error = ulaw_init (psf) ;
182
2
          break ;
183
184
2
    case SF_FORMAT_ALAW :
185
2
          error = alaw_init (psf) ;
186
2
          break ;
187
188
    /* Lite remove start */
189
2
    case SF_FORMAT_FLOAT :
190
2
          error = float32_init (psf) ;
191
2
          break ;
192
193
2
    case SF_FORMAT_DOUBLE :
194
2
          error = double64_init (psf) ;
195
2
          break ;
196
197
702
    case SF_FORMAT_ALAC_16 :
198
1.07k
    case SF_FORMAT_ALAC_20 :
199
1.75k
    case SF_FORMAT_ALAC_24 :
200
1.94k
    case SF_FORMAT_ALAC_32 :
201
1.94k
          if (psf->file.mode == SFM_READ)
202
            /* Only pass the ALAC_DECODER_INFO in read mode. */
203
1.94k
            error = alac_init (psf, &pcaf->alac) ;
204
0
          else
205
0
            error = alac_init (psf, NULL) ;
206
1.94k
          break ;
207
208
    /* Lite remove end */
209
210
15
    default :
211
15
      return SFE_UNSUPPORTED_ENCODING ;
212
1.97k
    } ;
213
214
1.96k
  return error ;
215
1.97k
} /* caf_open */
216
217
static int
218
caf_close (SF_PRIVATE *psf)
219
1.97k
{
220
1.97k
  if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
221
0
  { caf_write_tailer (psf) ;
222
0
    caf_write_header (psf, SF_TRUE) ;
223
0
    } ;
224
225
1.97k
  return 0 ;
226
1.97k
} /* caf_close */
227
228
static int
229
caf_command (SF_PRIVATE * psf, int command, void * UNUSED (data), int UNUSED (datasize))
230
0
{ CAF_PRIVATE *pcaf ;
231
232
0
  if ((pcaf = psf->container_data) == NULL)
233
0
    return SFE_INTERNAL ;
234
235
0
  switch (command)
236
0
  { case SFC_SET_CHANNEL_MAP_INFO :
237
0
      pcaf->chanmap_tag = aiff_caf_find_channel_layout_tag (psf->channel_map, psf->sf.channels) ;
238
0
      return (pcaf->chanmap_tag != 0) ;
239
240
0
    default :
241
0
      break ;
242
0
  } ;
243
244
0
  return 0 ;
245
0
} /* caf_command */
246
247
/*------------------------------------------------------------------------------
248
*/
249
250
static int
251
decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc)
252
2.46k
{ int format = SF_FORMAT_CAF ;
253
254
2.46k
  psf->sf.channels = desc->channels_per_frame ;
255
256
2.46k
  if (desc->fmt_id == alac_MARKER)
257
1.95k
  { CAF_PRIVATE *pcaf ;
258
259
1.95k
    if ((pcaf = psf->container_data) != NULL)
260
1.95k
    { switch (desc->fmt_flags)
261
1.95k
      { case 1 :
262
702
          pcaf->alac.bits_per_sample = 16 ;
263
702
          format |= SF_FORMAT_ALAC_16 ;
264
702
          break ;
265
376
        case 2 :
266
376
          pcaf->alac.bits_per_sample = 20 ;
267
376
          format |= SF_FORMAT_ALAC_20 ;
268
376
          break ;
269
679
        case 3 :
270
679
          pcaf->alac.bits_per_sample = 24 ;
271
679
          format |= SF_FORMAT_ALAC_24 ;
272
679
          break ;
273
187
        case 4 :
274
187
          pcaf->alac.bits_per_sample = 32 ;
275
187
          format |= SF_FORMAT_ALAC_32 ;
276
187
          break ;
277
15
        default :
278
15
          psf_log_printf (psf, "Bad ALAC format flag value of %d\n", desc->fmt_flags) ;
279
1.95k
        } ;
280
281
1.95k
      pcaf->alac.frames_per_packet = desc->frames_per_packet ;
282
1.95k
      } ;
283
284
1.95k
    return format ;
285
1.95k
    } ;
286
287
505
  format |= psf->endian == SF_ENDIAN_LITTLE ? SF_ENDIAN_LITTLE : 0 ;
288
289
505
  if (desc->fmt_id == lpcm_MARKER && desc->fmt_flags & 1)
290
74
  { /* Floating point data. */
291
74
    if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
292
2
    { psf->bytewidth = 4 ;
293
2
      return format | SF_FORMAT_FLOAT ;
294
72
      } ;
295
72
    if (desc->bits_per_chan == 64 && desc->pkt_bytes == 8 * desc->channels_per_frame)
296
2
    { psf->bytewidth = 8 ;
297
2
      return format | SF_FORMAT_DOUBLE ;
298
70
      } ;
299
501
    } ;
300
301
501
  if (desc->fmt_id == lpcm_MARKER && (desc->fmt_flags & 1) == 0)
302
133
  { /* Integer data. */
303
133
    if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
304
2
    { psf->bytewidth = 4 ;
305
2
      return format | SF_FORMAT_PCM_32 ;
306
131
      } ;
307
131
    if (desc->bits_per_chan == 24 && desc->pkt_bytes == 3 * desc->channels_per_frame)
308
2
    { psf->bytewidth = 3 ;
309
2
      return format | SF_FORMAT_PCM_24 ;
310
129
      } ;
311
129
    if (desc->bits_per_chan == 16 && desc->pkt_bytes == 2 * desc->channels_per_frame)
312
2
    { psf->bytewidth = 2 ;
313
2
      return format | SF_FORMAT_PCM_16 ;
314
127
      } ;
315
127
    if (desc->bits_per_chan == 8 && desc->pkt_bytes == 1 * desc->channels_per_frame)
316
2
    { psf->bytewidth = 1 ;
317
2
      return format | SF_FORMAT_PCM_S8 ;
318
125
      } ;
319
493
    } ;
320
321
493
  if (desc->fmt_id == alaw_MARKER && desc->bits_per_chan == 8)
322
2
  { psf->bytewidth = 1 ;
323
2
    return format | SF_FORMAT_ALAW ;
324
491
    } ;
325
326
491
  if (desc->fmt_id == ulaw_MARKER && desc->bits_per_chan == 8)
327
2
  { psf->bytewidth = 1 ;
328
2
    return format | SF_FORMAT_ULAW ;
329
489
    } ;
330
331
489
  psf_log_printf (psf, "**** Unknown format identifier.\n") ;
332
333
489
  return 0 ;
334
491
} /* decode_desc_chunk */
335
336
static int
337
caf_read_header (SF_PRIVATE *psf)
338
4.45k
{ CAF_PRIVATE *pcaf ;
339
4.45k
  BUF_UNION ubuf ;
340
4.45k
  DESC_CHUNK desc ;
341
4.45k
  sf_count_t chunk_size ;
342
4.45k
  double srate ;
343
4.45k
  short version, flags ;
344
4.45k
  int marker, k, have_data = 0, error ;
345
346
4.45k
  if ((pcaf = psf->container_data) == NULL)
347
0
    return SFE_INTERNAL ;
348
349
4.45k
  memset (&desc, 0, sizeof (desc)) ;
350
351
  /* Set position to start of file to begin reading header. */
352
4.45k
  psf_binheader_readf (psf, "pmE2E2", 0, &marker, &version, &flags) ;
353
4.45k
  psf_log_printf (psf, "%M\n  Version : %d\n  Flags   : %x\n", marker, version, flags) ;
354
4.45k
  if (marker != caff_MARKER)
355
0
    return SFE_CAF_NOT_CAF ;
356
357
4.45k
  psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, ubuf.ucbuf, 8) ;
358
4.45k
  srate = double64_be_read (ubuf.ucbuf) ;
359
4.45k
  snprintf (ubuf.cbuf, sizeof (ubuf.cbuf), "%5.3f", srate) ;
360
4.45k
  psf_log_printf (psf, "%M : %D\n  Sample rate  : %s\n", marker, chunk_size, ubuf.cbuf) ;
361
4.45k
  if (marker != desc_MARKER)
362
0
    return SFE_CAF_NO_DESC ;
363
364
4.45k
  if (chunk_size < SIGNED_SIZEOF (DESC_CHUNK))
365
140
  { psf_log_printf (psf, "**** Chunk size too small. Should be > 32 bytes.\n") ;
366
140
    return SFE_MALFORMED_FILE ;
367
4.31k
    } ;
368
369
4.31k
  psf->sf.samplerate = psf_lrint (srate) ;
370
371
4.31k
  psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.frames_per_packet,
372
4.31k
      &desc.channels_per_frame, &desc.bits_per_chan) ;
373
4.31k
  psf_log_printf (psf, "  Format id    : %M\n  Format flags : %x\n  Bytes / packet   : %u\n"
374
4.31k
      "  Frames / packet  : %u\n  Channels / frame : %u\n  Bits / channel   : %u\n",
375
4.31k
      desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.frames_per_packet, desc.channels_per_frame, desc.bits_per_chan) ;
376
377
4.31k
  if (desc.channels_per_frame > SF_MAX_CHANNELS)
378
9
  { psf_log_printf (psf, "**** Bad channels per frame value %u.\n", desc.channels_per_frame) ;
379
9
    return SFE_MALFORMED_FILE ;
380
4.31k
    } ;
381
382
4.31k
  if (chunk_size > SIGNED_SIZEOF (DESC_CHUNK))
383
4.30k
    psf_binheader_readf (psf, "j", (int) (chunk_size - sizeof (DESC_CHUNK))) ;
384
385
4.31k
  psf->sf.channels = desc.channels_per_frame ;
386
387
22.7k
  while (1)
388
22.7k
  { marker = 0 ;
389
22.7k
    chunk_size = 0 ;
390
391
22.7k
    psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ;
392
22.7k
    if (marker == 0)
393
328
    { sf_count_t pos = psf_ftell (psf) ;
394
328
      psf_log_printf (psf, "Have 0 marker at position %D (0x%x).\n", pos, pos) ;
395
328
      break ;
396
22.3k
      } ;
397
22.3k
    if (chunk_size < 0)
398
310
    { psf_log_printf (psf, "%M : %D *** Should be >= 0 ***\n", marker, chunk_size) ;
399
310
      break ;
400
22.0k
      } ;
401
22.0k
    if (chunk_size > psf->filelength)
402
906
      break ;
403
404
21.1k
    psf_store_read_chunk_u32 (&psf->rchunks, marker, psf_ftell (psf), chunk_size) ;
405
406
21.1k
    switch (marker)
407
21.1k
    { case peak_MARKER :
408
362
        psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
409
362
        if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels))
410
6
        { psf_binheader_readf (psf, "j", (size_t) chunk_size) ;
411
6
          psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
412
6
          return SFE_CAF_BAD_PEAK ;
413
356
          } ;
414
415
356
        if (psf->peak_info)
416
317
        { psf_log_printf (psf, "*** Found existing peak info, using last one.\n") ;
417
317
          free (psf->peak_info) ;
418
317
          psf->peak_info = NULL ;
419
317
          } ;
420
356
        if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
421
0
          return SFE_MALLOC_FAILED ;
422
423
        /* read in rest of PEAK chunk. */
424
356
        psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ;
425
356
        psf_log_printf (psf, "  edit count : %d\n", psf->peak_info->edit_number) ;
426
427
356
        psf_log_printf (psf, "     Ch   Position       Value\n") ;
428
1.15k
        for (k = 0 ; k < psf->sf.channels ; k++)
429
801
        { sf_count_t position ;
430
801
          float value ;
431
432
801
          psf_binheader_readf (psf, "Ef8", &value, &position) ;
433
801
          psf->peak_info->peaks [k].value = value ;
434
801
          psf->peak_info->peaks [k].position = position ;
435
436
801
          snprintf (ubuf.cbuf, sizeof (ubuf.cbuf), "    %2d   %-12" PRId64 "   %g\n", k, position, value) ;
437
801
          psf_log_printf (psf, ubuf.cbuf) ;
438
801
          } ;
439
440
356
        psf->peak_info->peak_loc = SF_PEAK_START ;
441
356
        break ;
442
443
4.37k
      case chan_MARKER :
444
4.37k
        if (chunk_size < 12)
445
2.10k
        { psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ;
446
2.10k
          psf_binheader_readf (psf, "j", (size_t) chunk_size) ;
447
2.10k
          break ;
448
2.10k
          }
449
450
2.27k
        psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
451
452
2.27k
        if ((error = caf_read_chanmap (psf, chunk_size)))
453
0
          return error ;
454
2.27k
        break ;
455
456
2.27k
      case free_MARKER :
457
168
        psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
458
168
        psf_binheader_readf (psf, "j", (size_t) chunk_size) ;
459
168
        break ;
460
461
3.05k
      case data_MARKER :
462
3.05k
        psf_binheader_readf (psf, "E4", &k) ;
463
3.05k
        if (chunk_size == -1)
464
0
        { psf_log_printf (psf, "%M : -1\n") ;
465
0
          chunk_size = psf->filelength - psf->header.indx ;
466
0
          }
467
3.05k
        else if (psf->filelength > 0 && chunk_size > psf->filelength - psf->header.indx + 10)
468
107
        { psf_log_printf (psf, "%M : %D (should be %D)\n", marker, chunk_size, psf->filelength - psf->header.indx - 8) ;
469
107
          psf->datalength = psf->filelength - psf->header.indx - 8 ;
470
107
          }
471
2.95k
        else
472
2.95k
        { psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
473
          /* Subtract the 4 bytes of the 'edit' field above. */
474
2.95k
          psf->datalength = chunk_size - 4 ;
475
2.95k
          } ;
476
477
3.05k
        psf_log_printf (psf, "  edit : %u\n", k) ;
478
479
3.05k
        psf->dataoffset = psf->header.indx ;
480
3.05k
        if (psf->datalength + psf->dataoffset < psf->filelength)
481
3.00k
          psf->dataend = psf->datalength + psf->dataoffset ;
482
483
3.05k
        psf_binheader_readf (psf, "j", (size_t) psf->datalength) ;
484
3.05k
        have_data = 1 ;
485
3.05k
        break ;
486
487
2.94k
      case kuki_MARKER :
488
2.94k
        psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
489
2.94k
        pcaf->alac.kuki_offset = psf_ftell (psf) - 12 ;
490
2.94k
        psf_binheader_readf (psf, "j", (size_t) chunk_size) ;
491
2.94k
        break ;
492
493
5.27k
      case pakt_MARKER :
494
5.27k
        if (chunk_size < 24)
495
7
        { psf_log_printf (psf, "%M : %D (should be > 24)\n", marker, chunk_size) ;
496
7
          return SFE_MALFORMED_FILE ;
497
7
          }
498
5.26k
        else if (chunk_size > psf->filelength - psf->header.indx)
499
11
        { psf_log_printf (psf, "%M : %D (should be < %D)\n", marker, chunk_size, psf->filelength - psf->header.indx) ;
500
11
          return SFE_MALFORMED_FILE ;
501
11
          }
502
5.25k
        else
503
5.25k
          psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
504
505
5.25k
        psf_binheader_readf (psf, "E8844", &pcaf->alac.packets, &pcaf->alac.valid_frames,
506
5.25k
                  &pcaf->alac.priming_frames, &pcaf->alac.remainder_frames) ;
507
508
5.25k
        psf_log_printf (psf,
509
5.25k
            "  Packets          : %D\n"
510
5.25k
            "  Valid frames     : %D\n"
511
5.25k
            "  Priming frames   : %d\n"
512
5.25k
            "  Remainder frames : %d\n",
513
5.25k
            pcaf->alac.packets, pcaf->alac.valid_frames, pcaf->alac.priming_frames,
514
5.25k
            pcaf->alac.remainder_frames
515
5.25k
            ) ;
516
517
5.25k
        if (pcaf->alac.packets == 0 && pcaf->alac.valid_frames == 0
518
1.47k
              && pcaf->alac.priming_frames == 0 && pcaf->alac.remainder_frames == 0)
519
765
          psf_log_printf (psf, "*** 'pakt' chunk header is all zero.\n") ;
520
521
5.25k
        pcaf->alac.pakt_offset = psf_ftell (psf) - 12 ;
522
5.25k
        psf_binheader_readf (psf, "j", (size_t) chunk_size - 24) ;
523
5.25k
        break ;
524
525
2.31k
      case info_MARKER :
526
2.31k
        if (chunk_size < 4)
527
7
        { psf_log_printf (psf, "%M : %D (should be > 4)\n", marker, chunk_size) ;
528
7
          return SFE_MALFORMED_FILE ;
529
7
          }
530
2.30k
        else if (chunk_size > psf->filelength - psf->header.indx)
531
23
        { psf_log_printf (psf, "%M : %D (should be < %D)\n", marker, chunk_size, psf->filelength - psf->header.indx) ;
532
23
          return SFE_MALFORMED_FILE ;
533
2.28k
          } ;
534
2.28k
        psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
535
2.28k
        if (chunk_size > 4)
536
1.70k
          caf_read_strings (psf, chunk_size - 4) ;
537
2.28k
        break ;
538
539
2.66k
      default :
540
2.66k
        psf_log_printf (psf, "%M : %D (skipped)\n", marker, chunk_size) ;
541
2.66k
        psf_binheader_readf (psf, "j", (size_t) chunk_size) ;
542
2.66k
        break ;
543
21.1k
      } ;
544
545
21.1k
    if (marker != data_MARKER && chunk_size >= 0xffffff00)
546
0
      break ;
547
548
21.1k
    if (! psf->sf.seekable && have_data)
549
0
      break ;
550
551
21.1k
    if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (chunk_size))
552
2.71k
    { psf_log_printf (psf, "End\n") ;
553
2.71k
      break ;
554
18.3k
      } ;
555
18.3k
    } ;
556
557
4.25k
  if (have_data == 0)
558
1.79k
  { psf_log_printf (psf, "**** Error, could not find 'data' chunk.\n") ;
559
1.79k
    return SFE_MALFORMED_FILE ;
560
2.46k
    } ;
561
562
2.46k
  psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ;
563
564
2.46k
  psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
565
566
2.46k
  if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0)
567
489
    return SFE_UNSUPPORTED_ENCODING ;
568
569
1.97k
  if (psf->bytewidth > 0)
570
16
    psf->sf.frames = psf->datalength / psf->bytewidth ;
571
572
1.97k
  return 0 ;
573
2.46k
} /* caf_read_header */
574
575
/*------------------------------------------------------------------------------
576
*/
577
578
static int
579
caf_write_header (SF_PRIVATE *psf, int calc_length)
580
0
{ BUF_UNION ubuf ;
581
0
  CAF_PRIVATE *pcaf ;
582
0
  DESC_CHUNK desc ;
583
0
  sf_count_t current ;
584
0
  uint32_t uk ;
585
0
  int subformat, append_free_block = SF_TRUE ;
586
587
0
  if ((pcaf = psf->container_data) == NULL)
588
0
    return SFE_INTERNAL ;
589
590
0
  memset (&desc, 0, sizeof (desc)) ;
591
592
0
  current = psf_ftell (psf) ;
593
594
0
  if (calc_length)
595
0
  { psf->filelength = psf_get_filelen (psf) ;
596
597
0
    psf->datalength = psf->filelength - psf->dataoffset ;
598
599
0
    if (psf->dataend)
600
0
      psf->datalength -= psf->filelength - psf->dataend ;
601
602
0
    if (psf->bytewidth > 0)
603
0
      psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
604
0
    } ;
605
606
  /* Reset the current header length to zero. */
607
0
  psf->header.ptr [0] = 0 ;
608
0
  psf->header.indx = 0 ;
609
0
  psf_fseek (psf, 0, SEEK_SET) ;
610
611
  /* 'caff' marker, version and flags. */
612
0
  psf_binheader_writef (psf, "Em22", BHWm (caff_MARKER), BHW2 (1), BHW2 (0)) ;
613
614
  /* 'desc' marker and chunk size. */
615
0
  psf_binheader_writef (psf, "Em8", BHWm (desc_MARKER), BHW8 ((sf_count_t) (sizeof (DESC_CHUNK)))) ;
616
617
0
  double64_be_write (1.0 * psf->sf.samplerate, ubuf.ucbuf) ;
618
0
  psf_binheader_writef (psf, "b", BHWv (ubuf.ucbuf), BHWz (8)) ;
619
620
0
  subformat = SF_CODEC (psf->sf.format) ;
621
622
0
  psf->endian = SF_ENDIAN (psf->sf.format) ;
623
624
0
  if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU))
625
0
    psf->endian = SF_ENDIAN_BIG ;
626
0
  else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_LITTLE || psf->endian == SF_ENDIAN_CPU))
627
0
    psf->endian = SF_ENDIAN_LITTLE ;
628
629
0
  if (psf->endian == SF_ENDIAN_LITTLE)
630
0
    desc.fmt_flags = 2 ;
631
0
  else
632
0
    psf->endian = SF_ENDIAN_BIG ;
633
634
  /* initial section (same for all, it appears) */
635
0
  switch (subformat)
636
0
  { case SF_FORMAT_PCM_S8 :
637
0
      desc.fmt_id = lpcm_MARKER ;
638
0
      psf->bytewidth = 1 ;
639
0
      desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
640
0
      desc.frames_per_packet = 1 ;
641
0
      desc.channels_per_frame = psf->sf.channels ;
642
0
      desc.bits_per_chan = 8 ;
643
0
      break ;
644
645
0
    case SF_FORMAT_PCM_16 :
646
0
      desc.fmt_id = lpcm_MARKER ;
647
0
      psf->bytewidth = 2 ;
648
0
      desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
649
0
      desc.frames_per_packet = 1 ;
650
0
      desc.channels_per_frame = psf->sf.channels ;
651
0
      desc.bits_per_chan = 16 ;
652
0
      break ;
653
654
0
    case SF_FORMAT_PCM_24 :
655
0
      psf->bytewidth = 3 ;
656
0
      desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
657
0
      desc.frames_per_packet = 1 ;
658
0
      desc.channels_per_frame = psf->sf.channels ;
659
0
      desc.bits_per_chan = 24 ;
660
0
      desc.fmt_id = lpcm_MARKER ;
661
0
      break ;
662
663
0
    case SF_FORMAT_PCM_32 :
664
0
      desc.fmt_id = lpcm_MARKER ;
665
0
      psf->bytewidth = 4 ;
666
0
      desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
667
0
      desc.frames_per_packet = 1 ;
668
0
      desc.channels_per_frame = psf->sf.channels ;
669
0
      desc.bits_per_chan = 32 ;
670
0
      break ;
671
672
0
    case SF_FORMAT_FLOAT :
673
0
      desc.fmt_id = lpcm_MARKER ;
674
0
      desc.fmt_flags |= 1 ;
675
0
      psf->bytewidth = 4 ;
676
0
      desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
677
0
      desc.frames_per_packet = 1 ;
678
0
      desc.channels_per_frame = psf->sf.channels ;
679
0
      desc.bits_per_chan = 32 ;
680
0
      break ;
681
682
0
    case SF_FORMAT_DOUBLE :
683
0
      desc.fmt_id = lpcm_MARKER ;
684
0
      desc.fmt_flags |= 1 ;
685
0
      psf->bytewidth = 8 ;
686
0
      desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
687
0
      desc.frames_per_packet = 1 ;
688
0
      desc.channels_per_frame = psf->sf.channels ;
689
0
      desc.bits_per_chan = 64 ;
690
0
      break ;
691
692
0
    case SF_FORMAT_ALAW :
693
0
      desc.fmt_id = alaw_MARKER ;
694
0
      psf->bytewidth = 1 ;
695
0
      desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
696
0
      desc.frames_per_packet = 1 ;
697
0
      desc.channels_per_frame = psf->sf.channels ;
698
0
      desc.bits_per_chan = 8 ;
699
0
      break ;
700
701
0
    case SF_FORMAT_ULAW :
702
0
      desc.fmt_id = ulaw_MARKER ;
703
0
      psf->bytewidth = 1 ;
704
0
      desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
705
0
      desc.frames_per_packet = 1 ;
706
0
      desc.channels_per_frame = psf->sf.channels ;
707
0
      desc.bits_per_chan = 8 ;
708
0
      break ;
709
710
0
    case SF_FORMAT_ALAC_16 :
711
0
    case SF_FORMAT_ALAC_20 :
712
0
    case SF_FORMAT_ALAC_24 :
713
0
    case SF_FORMAT_ALAC_32 :
714
0
      desc.fmt_id = alac_MARKER ;
715
0
      desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
716
0
      desc.channels_per_frame = psf->sf.channels ;
717
0
      alac_get_desc_chunk_items (subformat, &desc.fmt_flags, &desc.frames_per_packet) ;
718
0
      append_free_block = SF_FALSE ;
719
0
      break ;
720
721
0
    default :
722
0
      return SFE_UNIMPLEMENTED ;
723
0
    } ;
724
725
0
  psf_binheader_writef (psf, "mE44444", BHWm (desc.fmt_id), BHW4 (desc.fmt_flags), BHW4 (desc.pkt_bytes), BHW4 (desc.frames_per_packet), BHW4 (desc.channels_per_frame), BHW4 (desc.bits_per_chan)) ;
726
727
0
  caf_write_strings (psf, SF_STR_LOCATE_START) ;
728
729
0
  if (psf->peak_info != NULL)
730
0
  { int k ;
731
0
    psf_binheader_writef (psf, "Em84", BHWm (peak_MARKER), BHW8 ((sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels)), BHW4 (psf->peak_info->edit_number)) ;
732
0
    for (k = 0 ; k < psf->sf.channels ; k++)
733
0
      psf_binheader_writef (psf, "Ef8", BHWf ((float) psf->peak_info->peaks [k].value), BHW8 (psf->peak_info->peaks [k].position)) ;
734
0
    } ;
735
736
0
  if (psf->channel_map && pcaf->chanmap_tag)
737
0
    psf_binheader_writef (psf, "Em8444", BHWm (chan_MARKER), BHW8 ((sf_count_t) 12), BHW4 (pcaf->chanmap_tag), BHW4 (0), BHW4 (0)) ;
738
739
  /* Write custom headers. */
740
0
  for (uk = 0 ; uk < psf->wchunks.used ; uk++)
741
0
    psf_binheader_writef (psf, "m44b", BHWm ((int) psf->wchunks.chunks [uk].mark32), BHW4 (0), BHW4 (psf->wchunks.chunks [uk].len), BHWv (psf->wchunks.chunks [uk].data), BHWz (psf->wchunks.chunks [uk].len)) ;
742
743
0
  if (append_free_block)
744
0
  { /* Add free chunk so that the actual audio data starts at a multiple 0x1000. */
745
0
    sf_count_t free_len = 0x1000 - psf->header.indx - 16 - 12 ;
746
0
    while (free_len < 0)
747
0
      free_len += 0x1000 ;
748
0
    psf_binheader_writef (psf, "Em8z", BHWm (free_MARKER), BHW8 (free_len), BHWz (free_len)) ;
749
0
    } ;
750
751
0
  psf_binheader_writef (psf, "Em84", BHWm (data_MARKER), BHW8 (psf->datalength + 4), BHW4 (0)) ;
752
753
0
  psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
754
0
  if (psf->error)
755
0
    return psf->error ;
756
757
0
  psf->dataoffset = psf->header.indx ;
758
0
  if (current < psf->dataoffset)
759
0
    psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
760
0
  else if (current > 0)
761
0
    psf_fseek (psf, current, SEEK_SET) ;
762
763
0
  return psf->error ;
764
0
} /* caf_write_header */
765
766
static int
767
caf_write_tailer (SF_PRIVATE *psf)
768
0
{
769
  /* Reset the current header buffer length to zero. */
770
0
  psf->header.ptr [0] = 0 ;
771
0
  psf->header.indx = 0 ;
772
773
0
  if (psf->bytewidth > 0 && psf->sf.seekable == SF_TRUE)
774
0
  { psf->datalength = psf->sf.frames * psf->bytewidth * psf->sf.channels ;
775
0
    psf->dataend = psf->dataoffset + psf->datalength ;
776
0
    } ;
777
778
0
  if (psf->dataend > 0)
779
0
    psf_fseek (psf, psf->dataend, SEEK_SET) ;
780
0
  else
781
0
    psf->dataend = psf_fseek (psf, 0, SEEK_END) ;
782
783
0
  if (psf->dataend & 1)
784
0
    psf_binheader_writef (psf, "z", BHWz (1)) ;
785
786
0
  if (psf->strings.flags & SF_STR_LOCATE_END)
787
0
    caf_write_strings (psf, SF_STR_LOCATE_END) ;
788
789
  /* Write the tailer. */
790
0
  if (psf->header.indx > 0)
791
0
    psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
792
793
0
  return 0 ;
794
0
} /* caf_write_tailer */
795
796
static int
797
caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size)
798
2.27k
{ const AIFF_CAF_CHANNEL_MAP * map_info ;
799
2.27k
  unsigned channel_bitmap, channel_decriptions, bytesread ;
800
2.27k
  int layout_tag ;
801
802
2.27k
  bytesread = psf_binheader_readf (psf, "E444", &layout_tag, &channel_bitmap, &channel_decriptions) ;
803
804
2.27k
  map_info = aiff_caf_of_channel_layout_tag (layout_tag) ;
805
806
2.27k
  psf_log_printf (psf, "  Tag    : %x\n", layout_tag) ;
807
2.27k
  if (map_info)
808
1.17k
    psf_log_printf (psf, "  Layout : %s\n", map_info->name) ;
809
810
2.27k
  if (bytesread < chunk_size)
811
1.43k
    psf_binheader_readf (psf, "j", chunk_size - bytesread) ;
812
813
2.27k
  if (map_info && map_info->channel_map != NULL)
814
834
  { size_t chanmap_size = SF_MIN (psf->sf.channels, layout_tag & 0xff) * sizeof (psf->channel_map [0]) ;
815
816
834
    free (psf->channel_map) ;
817
818
834
    if ((psf->channel_map = malloc (chanmap_size)) == NULL)
819
0
      return SFE_MALLOC_FAILED ;
820
821
834
    memcpy (psf->channel_map, map_info->channel_map, chanmap_size) ;
822
2.27k
    } ;
823
824
2.27k
  return 0 ;
825
2.27k
} /* caf_read_chanmap */
826
827
828
static uint32_t
829
string_hash32 (const char * str)
830
221k
{ uint32_t hash = 0x87654321 ;
831
832
615k
  while (str [0])
833
393k
  { hash = hash * 333 + str [0] ;
834
393k
    str ++ ;
835
393k
    } ;
836
837
221k
  return hash ;
838
221k
} /* string_hash32 */
839
840
static int
841
caf_read_strings (SF_PRIVATE * psf, sf_count_t chunk_size)
842
1.70k
{ char *buf ;
843
1.70k
  char *key, *value ;
844
1.70k
  uint32_t count, hash ;
845
846
1.70k
  if ((buf = malloc (chunk_size + 1)) == NULL)
847
0
    return (psf->error = SFE_MALLOC_FAILED) ;
848
849
1.70k
  psf_binheader_readf (psf, "E4b", &count, buf, (size_t) chunk_size) ;
850
1.70k
  psf_log_printf (psf, " count: %u\n", count) ;
851
852
  /* Force terminate `buf` to make sure. */
853
1.70k
  buf [chunk_size] = 0 ;
854
855
223k
  for (key = buf ; key < buf + chunk_size ; )
856
222k
  { value = key + strlen (key) + 1 ;
857
222k
    if (value > buf + chunk_size)
858
595
      break ;
859
221k
    psf_log_printf (psf, "   %-12s : %s\n", key, value) ;
860
861
221k
    hash = string_hash32 (key) ;
862
221k
    switch (hash)
863
221k
    { case 0xC4861943 : /* 'title' */
864
184
        psf_store_string (psf, SF_STR_TITLE, value) ;
865
184
        break ;
866
699
      case 0xAD47A394 : /* 'software' */
867
699
        psf_store_string (psf, SF_STR_SOFTWARE, value) ;
868
699
        break ;
869
388
      case 0x5D178E2A : /* 'copyright' */
870
388
        psf_store_string (psf, SF_STR_COPYRIGHT, value) ;
871
388
        break ;
872
529
      case 0x60E4D0C8 : /* 'artist' */
873
529
        psf_store_string (psf, SF_STR_ARTIST, value) ;
874
529
        break ;
875
278
      case 0x83B5D16A : /* 'genre' */
876
278
        psf_store_string (psf, SF_STR_GENRE, value) ;
877
278
        break ;
878
746
      case 0x15E5FC88 : /* 'comment' */
879
1.34k
      case 0x7C297D5B : /* 'comments' */
880
1.34k
        psf_store_string (psf, SF_STR_COMMENT, value) ;
881
1.34k
        break ;
882
611
      case 0x24A7C347 : /* 'tracknumber' */
883
611
        psf_store_string (psf, SF_STR_TRACKNUMBER, value) ;
884
611
        break ;
885
534
      case 0x50A31EB7 : /* 'date' */
886
534
        psf_store_string (psf, SF_STR_DATE, value) ;
887
534
        break ;
888
296
      case 0x6583545A : /* 'album' */
889
296
        psf_store_string (psf, SF_STR_ALBUM, value) ;
890
296
        break ;
891
432
      case 0xE7C64B6C : /* 'license' */
892
432
        psf_store_string (psf, SF_STR_LICENSE, value) ;
893
432
        break ;
894
216k
      default :
895
216k
        psf_log_printf (psf, " Unhandled hash 0x%x : /* '%s' */\n", hash, key) ;
896
216k
        break ;
897
221k
      } ;
898
899
221k
    key = value + strlen (value) + 1 ;
900
221k
    } ;
901
902
1.70k
  free (buf) ;
903
904
1.70k
  return 0 ;
905
1.70k
} /* caf_read_strings */
906
907
struct put_buffer
908
{ uint32_t index ;
909
  char s [16 * 1024] ;
910
} ;
911
912
static uint32_t
913
put_key_value (struct put_buffer * buf, const char * key, const char * value)
914
0
{ uint32_t written ;
915
916
0
  if (buf->index + strlen (key) + strlen (value) + 2 > sizeof (buf->s))
917
0
    return 0 ;
918
919
0
  written = snprintf (buf->s + buf->index, sizeof (buf->s) - buf->index, "%s%c%s%c", key, 0, value, 0) ;
920
921
0
  if (buf->index + written >= sizeof (buf->s))
922
0
    return 0 ;
923
924
0
  buf->index += written ;
925
0
  return 1 ;
926
0
} /* put_key_value */
927
928
static void
929
caf_write_strings (SF_PRIVATE * psf, int location)
930
0
{ struct put_buffer buf ;
931
0
  const char * cptr ;
932
0
  uint32_t k, string_count = 0 ;
933
934
0
  memset (&buf, 0, sizeof (buf)) ;
935
936
0
  for (k = 0 ; k < SF_MAX_STRINGS ; k++)
937
0
  { if (psf->strings.data [k].type == 0)
938
0
      break ;
939
940
0
    if (psf->strings.data [k].flags != location)
941
0
      continue ;
942
943
0
    if ((cptr = psf_get_string (psf, psf->strings.data [k].type)) == NULL)
944
0
      continue ;
945
946
0
    switch (psf->strings.data [k].type)
947
0
    { case SF_STR_TITLE :
948
0
        string_count += put_key_value (&buf, "title", cptr) ;
949
0
        break ;
950
0
      case SF_STR_COPYRIGHT :
951
0
        string_count += put_key_value (&buf, "copyright", cptr) ;
952
0
        break ;
953
0
      case SF_STR_SOFTWARE :
954
0
        string_count += put_key_value (&buf, "software", cptr) ;
955
0
        break ;
956
0
      case SF_STR_ARTIST :
957
0
        string_count += put_key_value (&buf, "artist", cptr) ;
958
0
        break ;
959
0
      case SF_STR_COMMENT :
960
0
        string_count += put_key_value (&buf, "comment", cptr) ;
961
0
        break ;
962
0
      case SF_STR_DATE :
963
0
        string_count += put_key_value (&buf, "date", cptr) ;
964
0
        break ;
965
0
      case SF_STR_ALBUM :
966
0
        string_count += put_key_value (&buf, "album", cptr) ;
967
0
        break ;
968
0
      case SF_STR_LICENSE :
969
0
        string_count += put_key_value (&buf, "license", cptr) ;
970
0
        break ;
971
0
      case SF_STR_TRACKNUMBER :
972
0
        string_count += put_key_value (&buf, "tracknumber", cptr) ;
973
0
        break ;
974
0
      case SF_STR_GENRE :
975
0
        string_count += put_key_value (&buf, "genre", cptr) ;
976
0
        break ;
977
978
0
      default :
979
0
        break ;
980
0
      } ;
981
0
    } ;
982
983
0
  if (string_count == 0 || buf.index == 0)
984
0
    return ;
985
986
0
  psf_binheader_writef (psf, "Em84b", BHWm (info_MARKER), BHW8 (buf.index + 4), BHW4 (string_count), BHWv (buf.s), BHWz (buf.index)) ;
987
0
} /* caf_write_strings */
988
989
/*==============================================================================
990
*/
991
992
static int
993
caf_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info)
994
0
{ return psf_save_write_chunk (&psf->wchunks, chunk_info) ;
995
0
} /* caf_set_chunk */
996
997
static SF_CHUNK_ITERATOR *
998
caf_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator)
999
3.01k
{ return psf_next_chunk_iterator (&psf->rchunks, iterator) ;
1000
3.01k
} /* caf_next_chunk_iterator */
1001
1002
static int
1003
caf_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info)
1004
1.81k
{ int indx ;
1005
1006
1.81k
  if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0)
1007
0
    return SFE_UNKNOWN_CHUNK ;
1008
1009
1.81k
  chunk_info->datalen = psf->rchunks.chunks [indx].len ;
1010
1011
1.81k
  return SFE_NO_ERROR ;
1012
1.81k
} /* caf_get_chunk_size */
1013
1014
static int
1015
caf_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info)
1016
1.81k
{ int indx ;
1017
1.81k
  sf_count_t pos ;
1018
1019
1.81k
  if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0)
1020
0
    return SFE_UNKNOWN_CHUNK ;
1021
1022
1.81k
  if (chunk_info->data == NULL)
1023
0
    return SFE_BAD_CHUNK_DATA_PTR ;
1024
1025
1.81k
  chunk_info->id_size = psf->rchunks.chunks [indx].id_size ;
1026
1.81k
  memcpy (chunk_info->id, psf->rchunks.chunks [indx].id, sizeof (chunk_info->id) / sizeof (*chunk_info->id)) ;
1027
1028
1.81k
  pos = psf_ftell (psf) ;
1029
1.81k
  psf_fseek (psf, psf->rchunks.chunks [indx].offset, SEEK_SET) ;
1030
1.81k
  psf_fread (chunk_info->data, SF_MIN (chunk_info->datalen, psf->rchunks.chunks [indx].len), 1, psf) ;
1031
1.81k
  psf_fseek (psf, pos, SEEK_SET) ;
1032
1033
1.81k
  return SFE_NO_ERROR ;
1034
1.81k
} /* caf_get_chunk_data */