1 // Derived from:
2
3 /* $OpenBSD: buffer.c,v 1.31 2006/08/03 03:34:41 deraadt Exp $ */
4 /*
5 * Author: Tatu Ylonen <ylo@cs.hut.fi>
6 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
7 * All rights reserved
8 * Functions for manipulating fifo buffers (that can grow if needed).
9 *
10 * As far as I am concerned, the code I have written for this software
11 * can be used freely for any purpose. Any derived versions of this
12 * software must be clearly marked as such, and if the derived work is
13 * incompatible with the protocol description in the RFC file, it must be
14 * called by a name other than "ssh" or "Secure Shell".
15 */
16
17 #include "buffer.h"
18
19 #define BUFFER_MAX_CHUNK 0x1400000
20 #define BUFFER_MAX_LEN 0x1400000
21 #define BUFFER_ALLOCSZ 0x002000
22 #define BUFFER_COMPACT_PERCENT 0.8
23
24 #define UnsignedToFloat(u) (((double)((long)(u - 2147483647L - 1))) + 2147483648.0)
25
26 /* Initializes the buffer structure. */
27
28 void
buffer_init(Buffer * buffer,uint32_t len)29 buffer_init(Buffer *buffer, uint32_t len)
30 {
31 if (!len) len = BUFFER_ALLOCSZ;
32
33 buffer->alloc = 0;
34 New(0, buffer->buf, (int)len, u_char);
35 buffer->alloc = len;
36 buffer->offset = 0;
37 buffer->end = 0;
38 buffer->cache = 0;
39 buffer->ncached = 0;
40
41 #ifdef AUDIO_SCAN_DEBUG
42 PerlIO_printf(PerlIO_stderr(), "Buffer allocated with %d bytes\n", len);
43 #endif
44 }
45
46 /* Allows easy reuse of a buffer, will init or clear buffer if it already exists */
47
48 void
buffer_init_or_clear(Buffer * buffer,uint32_t len)49 buffer_init_or_clear(Buffer *buffer, uint32_t len)
50 {
51 if (!buffer->alloc) {
52 buffer_init(buffer, len);
53 }
54 else {
55 buffer_clear(buffer);
56 }
57 }
58
59 /* Frees any memory used for the buffer. */
60
61 void
buffer_free(Buffer * buffer)62 buffer_free(Buffer *buffer)
63 {
64 if (buffer->alloc > 0) {
65 #ifdef AUDIO_SCAN_DEBUG
66 PerlIO_printf(PerlIO_stderr(), "Buffer high water mark: %d\n", buffer->alloc);
67 #endif
68 memset(buffer->buf, 0, buffer->alloc);
69 buffer->alloc = 0;
70 Safefree(buffer->buf);
71 }
72 }
73
74 /*
75 * Clears any data from the buffer, making it empty. This does not actually
76 * zero the memory.
77 */
78
79 void
buffer_clear(Buffer * buffer)80 buffer_clear(Buffer *buffer)
81 {
82 buffer->offset = 0;
83 buffer->end = 0;
84 buffer->cache = 0;
85 buffer->ncached = 0;
86 }
87
88 /* Appends data to the buffer, expanding it if necessary. */
89
90 void
buffer_append(Buffer * buffer,const void * data,uint32_t len)91 buffer_append(Buffer *buffer, const void *data, uint32_t len)
92 {
93 void *p;
94 p = buffer_append_space(buffer, len);
95 Copy(data, p, (int)len, u_char);
96 }
97
98 static int
buffer_compact(Buffer * buffer)99 buffer_compact(Buffer *buffer)
100 {
101 /*
102 * If the buffer is at least BUFFER_COMPACT_PERCENT empty, move the
103 * data to the beginning.
104 */
105 if (buffer->offset * 1.0 / buffer->alloc >= BUFFER_COMPACT_PERCENT ) {
106 #ifdef AUDIO_SCAN_DEBUG
107 PerlIO_printf(PerlIO_stderr(), "Buffer compacting (%d -> %d)\n", buffer->offset + buffer_len(buffer), buffer_len(buffer));
108 #endif
109 Move(buffer->buf + buffer->offset, buffer->buf, (int)(buffer->end - buffer->offset), u_char);
110 buffer->end -= buffer->offset;
111 buffer->offset = 0;
112 return (1);
113 }
114
115 return (0);
116 }
117
118 /*
119 * Appends space to the buffer, expanding the buffer if necessary. This does
120 * not actually copy the data into the buffer, but instead returns a pointer
121 * to the allocated region.
122 */
123
124 void *
buffer_append_space(Buffer * buffer,uint32_t len)125 buffer_append_space(Buffer *buffer, uint32_t len)
126 {
127 uint32_t newlen;
128 void *p;
129
130 if (len > BUFFER_MAX_CHUNK)
131 croak("buffer_append_space: len %u too large (max %u)", len, BUFFER_MAX_CHUNK);
132
133 /* If the buffer is empty, start using it from the beginning. */
134 if (buffer->offset == buffer->end) {
135 buffer->offset = 0;
136 buffer->end = 0;
137 }
138
139 restart:
140 /* If there is enough space to store all data, store it now. */
141 if (buffer->end + len <= buffer->alloc) {
142 p = buffer->buf + buffer->end;
143 buffer->end += len;
144 return p;
145 }
146
147 /* Compact data back to the start of the buffer if necessary */
148 if (buffer_compact(buffer))
149 goto restart;
150
151 /* Increase the size of the buffer and retry. */
152 if (buffer->alloc + len < 4096)
153 newlen = (buffer->alloc + len) * 2;
154 else
155 newlen = buffer->alloc + len + 4096;
156
157 if (newlen > BUFFER_MAX_LEN)
158 croak("buffer_append_space: alloc %u too large (max %u)",
159 newlen, BUFFER_MAX_LEN);
160 #ifdef AUDIO_SCAN_DEBUG
161 PerlIO_printf(PerlIO_stderr(), "Buffer extended to %d\n", newlen);
162 #endif
163 Renew(buffer->buf, (int)newlen, u_char);
164 buffer->alloc = newlen;
165 goto restart;
166 /* NOTREACHED */
167 }
168
169 /*
170 * Check whether an allocation of 'len' will fit in the buffer
171 * This must follow the same math as buffer_append_space
172 */
173 int
buffer_check_alloc(Buffer * buffer,uint32_t len)174 buffer_check_alloc(Buffer *buffer, uint32_t len)
175 {
176 if (buffer->offset == buffer->end) {
177 buffer->offset = 0;
178 buffer->end = 0;
179 }
180 restart:
181 if (buffer->end + len < buffer->alloc)
182 return (1);
183 if (buffer_compact(buffer))
184 goto restart;
185 if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN)
186 return (1);
187 return (0);
188 }
189
190 /* Returns the number of bytes of data in the buffer. */
191
192 uint32_t
buffer_len(Buffer * buffer)193 buffer_len(Buffer *buffer)
194 {
195 return buffer->end - buffer->offset;
196 }
197
198 /* Gets data from the beginning of the buffer. */
199
200 int
buffer_get_ret(Buffer * buffer,void * buf,uint32_t len)201 buffer_get_ret(Buffer *buffer, void *buf, uint32_t len)
202 {
203 if (len > buffer->end - buffer->offset) {
204 warn("buffer_get_ret: trying to get more bytes %d than in buffer %d", len, buffer->end - buffer->offset);
205 return (-1);
206 }
207
208 Copy(buffer->buf + buffer->offset, buf, (int)len, char);
209 buffer->offset += len;
210 return (0);
211 }
212
213 void
buffer_get(Buffer * buffer,void * buf,uint32_t len)214 buffer_get(Buffer *buffer, void *buf, uint32_t len)
215 {
216 if (buffer_get_ret(buffer, buf, len) == -1)
217 croak("buffer_get: buffer error");
218 }
219
220 /* Consumes the given number of bytes from the beginning of the buffer. */
221
222 int
buffer_consume_ret(Buffer * buffer,uint32_t bytes)223 buffer_consume_ret(Buffer *buffer, uint32_t bytes)
224 {
225 if (bytes > buffer->end - buffer->offset) {
226 warn("buffer_consume_ret: trying to get more bytes %d than in buffer %d", bytes, buffer->end - buffer->offset);
227 return (-1);
228 }
229
230 buffer->offset += bytes;
231 return (0);
232 }
233
234 void
buffer_consume(Buffer * buffer,uint32_t bytes)235 buffer_consume(Buffer *buffer, uint32_t bytes)
236 {
237 if (buffer_consume_ret(buffer, bytes) == -1)
238 croak("buffer_consume: buffer error");
239 }
240
241 /* Consumes the given number of bytes from the end of the buffer. */
242
243 int
buffer_consume_end_ret(Buffer * buffer,uint32_t bytes)244 buffer_consume_end_ret(Buffer *buffer, uint32_t bytes)
245 {
246 if (bytes > buffer->end - buffer->offset)
247 return (-1);
248
249 buffer->end -= bytes;
250 return (0);
251 }
252
253 void
buffer_consume_end(Buffer * buffer,uint32_t bytes)254 buffer_consume_end(Buffer *buffer, uint32_t bytes)
255 {
256 if (buffer_consume_end_ret(buffer, bytes) == -1)
257 croak("buffer_consume_end: trying to get more bytes %d than in buffer %d", bytes, buffer->end - buffer->offset);
258 }
259
260 /* Returns a pointer to the first used byte in the buffer. */
261
262 void *
buffer_ptr(Buffer * buffer)263 buffer_ptr(Buffer *buffer)
264 {
265 return buffer->buf + buffer->offset;
266 }
267
268 // Dumps the contents of the buffer to stderr.
269 // Based on: http://sws.dett.de/mini/hexdump-c/
270 #ifdef AUDIO_SCAN_DEBUG
271 void
buffer_dump(Buffer * buffer,uint32_t size)272 buffer_dump(Buffer *buffer, uint32_t size)
273 {
274 unsigned char *data = buffer->buf;
275 unsigned char c;
276 int i = 1;
277 int n;
278 char bytestr[4] = {0};
279 char hexstr[ 16*3 + 5] = {0};
280 char charstr[16*1 + 5] = {0};
281
282 if (!size) {
283 size = buffer->end - buffer->offset;
284 }
285
286 for (n = buffer->offset; n < buffer->offset + size; n++) {
287 c = data[n];
288
289 /* store hex str (for left side) */
290 snprintf(bytestr, sizeof(bytestr), "%02x ", c);
291 strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
292
293 /* store char str (for right side) */
294 if (isalnum(c) == 0) {
295 c = '.';
296 }
297 snprintf(bytestr, sizeof(bytestr), "%c", c);
298 strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
299
300 if (i % 16 == 0) {
301 /* line completed */
302 PerlIO_printf(PerlIO_stderr(), "%-50.50s %s\n", hexstr, charstr);
303 hexstr[0] = 0;
304 charstr[0] = 0;
305 }
306 i++;
307 }
308
309 if (strlen(hexstr) > 0) {
310 /* print rest of buffer if not empty */
311 PerlIO_printf(PerlIO_stderr(), "%-50.50s %s\n", hexstr, charstr);
312 }
313 }
314 #endif
315
316 // Useful functions from bufaux.c
317
318 /*
319 * Returns a character from the buffer (0 - 255).
320 */
321 int
buffer_get_char_ret(char * ret,Buffer * buffer)322 buffer_get_char_ret(char *ret, Buffer *buffer)
323 {
324 if (buffer_get_ret(buffer, ret, 1) == -1) {
325 warn("buffer_get_char_ret: buffer_get_ret failed");
326 return (-1);
327 }
328
329 return (0);
330 }
331
332 int
buffer_get_char(Buffer * buffer)333 buffer_get_char(Buffer *buffer)
334 {
335 char ch;
336
337 if (buffer_get_char_ret(&ch, buffer) == -1)
338 croak("buffer_get_char: buffer error");
339 return (u_char) ch;
340 }
341
342 uint32_t
get_u32le(const void * vp)343 get_u32le(const void *vp)
344 {
345 const u_char *p = (const u_char *)vp;
346 uint32_t v;
347
348 v = (uint32_t)p[3] << 24;
349 v |= (uint32_t)p[2] << 16;
350 v |= (uint32_t)p[1] << 8;
351 v |= (uint32_t)p[0];
352
353 return (v);
354 }
355
356 int
buffer_get_int_le_ret(uint32_t * ret,Buffer * buffer)357 buffer_get_int_le_ret(uint32_t *ret, Buffer *buffer)
358 {
359 u_char buf[4];
360
361 if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
362 return (-1);
363 *ret = get_u32le(buf);
364 return (0);
365 }
366
367 uint32_t
buffer_get_int_le(Buffer * buffer)368 buffer_get_int_le(Buffer *buffer)
369 {
370 uint32_t ret;
371
372 if (buffer_get_int_le_ret(&ret, buffer) == -1)
373 croak("buffer_get_int_le: buffer error");
374
375 return (ret);
376 }
377
378 uint32_t
get_u32(const void * vp)379 get_u32(const void *vp)
380 {
381 const u_char *p = (const u_char *)vp;
382 uint32_t v;
383
384 v = (uint32_t)p[0] << 24;
385 v |= (uint32_t)p[1] << 16;
386 v |= (uint32_t)p[2] << 8;
387 v |= (uint32_t)p[3];
388
389 return (v);
390 }
391
392 int
buffer_get_int_ret(uint32_t * ret,Buffer * buffer)393 buffer_get_int_ret(uint32_t *ret, Buffer *buffer)
394 {
395 u_char buf[4];
396
397 if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
398 return (-1);
399 *ret = get_u32(buf);
400 return (0);
401 }
402
403 uint32_t
buffer_get_int(Buffer * buffer)404 buffer_get_int(Buffer *buffer)
405 {
406 uint32_t ret;
407
408 if (buffer_get_int_ret(&ret, buffer) == -1)
409 croak("buffer_get_int: buffer error");
410
411 return (ret);
412 }
413
414 uint32_t
get_u24(const void * vp)415 get_u24(const void *vp)
416 {
417 const u_char *p = (const u_char *)vp;
418 uint32_t v;
419
420 v = (uint32_t)p[0] << 16;
421 v |= (uint32_t)p[1] << 8;
422 v |= (uint32_t)p[2];
423
424 return (v);
425 }
426
427 int
buffer_get_int24_ret(uint32_t * ret,Buffer * buffer)428 buffer_get_int24_ret(uint32_t *ret, Buffer *buffer)
429 {
430 u_char buf[3];
431
432 if (buffer_get_ret(buffer, (char *) buf, 3) == -1)
433 return (-1);
434 *ret = get_u24(buf);
435 return (0);
436 }
437
438 uint32_t
buffer_get_int24(Buffer * buffer)439 buffer_get_int24(Buffer *buffer)
440 {
441 uint32_t ret;
442
443 if (buffer_get_int24_ret(&ret, buffer) == -1)
444 croak("buffer_get_int24: buffer error");
445
446 return (ret);
447 }
448
449 uint32_t
get_u24le(const void * vp)450 get_u24le(const void *vp)
451 {
452 const u_char *p = (const u_char *)vp;
453 uint32_t v;
454
455 v = (uint32_t)p[2] << 16;
456 v |= (uint32_t)p[1] << 8;
457 v |= (uint32_t)p[0];
458
459 return (v);
460 }
461
462 int
buffer_get_int24_le_ret(uint32_t * ret,Buffer * buffer)463 buffer_get_int24_le_ret(uint32_t *ret, Buffer *buffer)
464 {
465 u_char buf[3];
466
467 if (buffer_get_ret(buffer, (char *) buf, 3) == -1)
468 return (-1);
469 *ret = get_u24le(buf);
470 return (0);
471 }
472
473 uint32_t
buffer_get_int24_le(Buffer * buffer)474 buffer_get_int24_le(Buffer *buffer)
475 {
476 uint32_t ret;
477
478 if (buffer_get_int24_le_ret(&ret, buffer) == -1)
479 croak("buffer_get_int24_le: buffer error");
480
481 return (ret);
482 }
483
484 uint64_t
get_u64le(const void * vp)485 get_u64le(const void *vp)
486 {
487 const u_char *p = (const u_char *)vp;
488 uint64_t v;
489
490 v = (uint64_t)p[7] << 56;
491 v |= (uint64_t)p[6] << 48;
492 v |= (uint64_t)p[5] << 40;
493 v |= (uint64_t)p[4] << 32;
494 v |= (uint64_t)p[3] << 24;
495 v |= (uint64_t)p[2] << 16;
496 v |= (uint64_t)p[1] << 8;
497 v |= (uint64_t)p[0];
498
499 return (v);
500 }
501
502 int
buffer_get_int64_le_ret(uint64_t * ret,Buffer * buffer)503 buffer_get_int64_le_ret(uint64_t *ret, Buffer *buffer)
504 {
505 u_char buf[8];
506
507 if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
508 return (-1);
509 *ret = get_u64le(buf);
510 return (0);
511 }
512
513 uint64_t
buffer_get_int64_le(Buffer * buffer)514 buffer_get_int64_le(Buffer *buffer)
515 {
516 uint64_t ret;
517
518 if (buffer_get_int64_le_ret(&ret, buffer) == -1)
519 croak("buffer_get_int64_le: buffer error");
520
521 return (ret);
522 }
523
524 uint64_t
get_u64(const void * vp)525 get_u64(const void *vp)
526 {
527 const u_char *p = (const u_char *)vp;
528 uint64_t v;
529
530 v = (uint64_t)p[0] << 56;
531 v |= (uint64_t)p[1] << 48;
532 v |= (uint64_t)p[2] << 40;
533 v |= (uint64_t)p[3] << 32;
534 v |= (uint64_t)p[4] << 24;
535 v |= (uint64_t)p[5] << 16;
536 v |= (uint64_t)p[6] << 8;
537 v |= (uint64_t)p[7];
538
539 return (v);
540 }
541
542 int
buffer_get_int64_ret(uint64_t * ret,Buffer * buffer)543 buffer_get_int64_ret(uint64_t *ret, Buffer *buffer)
544 {
545 u_char buf[8];
546
547 if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
548 return (-1);
549 *ret = get_u64(buf);
550 return (0);
551 }
552
553 uint64_t
buffer_get_int64(Buffer * buffer)554 buffer_get_int64(Buffer *buffer)
555 {
556 uint64_t ret;
557
558 if (buffer_get_int64_ret(&ret, buffer) == -1)
559 croak("buffer_get_int64_le: buffer error");
560
561 return (ret);
562 }
563
564 uint16_t
get_u16le(const void * vp)565 get_u16le(const void *vp)
566 {
567 const u_char *p = (const u_char *)vp;
568 uint16_t v;
569
570 v = (uint16_t)p[1] << 8;
571 v |= (uint16_t)p[0];
572
573 return (v);
574 }
575
576 int
buffer_get_short_le_ret(uint16_t * ret,Buffer * buffer)577 buffer_get_short_le_ret(uint16_t *ret, Buffer *buffer)
578 {
579 u_char buf[2];
580
581 if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
582 return (-1);
583 *ret = get_u16le(buf);
584 return (0);
585 }
586
587 uint16_t
buffer_get_short_le(Buffer * buffer)588 buffer_get_short_le(Buffer *buffer)
589 {
590 uint16_t ret;
591
592 if (buffer_get_short_le_ret(&ret, buffer) == -1)
593 croak("buffer_get_short_le: buffer error");
594
595 return (ret);
596 }
597
598 uint16_t
get_u16(const void * vp)599 get_u16(const void *vp)
600 {
601 const u_char *p = (const u_char *)vp;
602 uint16_t v;
603
604 v = (uint16_t)p[0] << 8;
605 v |= (uint16_t)p[1];
606
607 return (v);
608 }
609
610 int
buffer_get_short_ret(uint16_t * ret,Buffer * buffer)611 buffer_get_short_ret(uint16_t *ret, Buffer *buffer)
612 {
613 u_char buf[2];
614
615 if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
616 return (-1);
617 *ret = get_u16(buf);
618 return (0);
619 }
620
621 uint16_t
buffer_get_short(Buffer * buffer)622 buffer_get_short(Buffer *buffer)
623 {
624 uint16_t ret;
625
626 if (buffer_get_short_ret(&ret, buffer) == -1)
627 croak("buffer_get_short: buffer error");
628
629 return (ret);
630 }
631
632 /*
633 * Stores a character in the buffer.
634 */
635 void
buffer_put_char(Buffer * buffer,int value)636 buffer_put_char(Buffer *buffer, int value)
637 {
638 char ch = value;
639
640 buffer_append(buffer, &ch, 1);
641 }
642
643 // Read a null-terminated UTF-8 string
644 // Caller must manage utf8 buffer (init/free)
645 uint32_t
buffer_get_utf8(Buffer * buffer,Buffer * utf8,uint32_t len_hint)646 buffer_get_utf8(Buffer *buffer, Buffer *utf8, uint32_t len_hint)
647 {
648 int i = 0;
649 unsigned char *bptr = buffer_ptr(buffer);
650
651 if (!len_hint) return 0;
652
653 for (i = 0; i < len_hint; i++) {
654 uint8_t c = bptr[i];
655
656 buffer_put_char(utf8, c);
657
658 if (c == 0) {
659 i++;
660 break;
661 }
662 }
663
664 // Consume string + null
665 buffer_consume(buffer, i);
666
667 // Add null if one wasn't provided
668 if ( (utf8->buf + utf8->end - 1)[0] != 0 ) {
669 buffer_put_char(utf8, 0);
670 }
671
672 #ifdef AUDIO_SCAN_DEBUG
673 //DEBUG_TRACE("utf8 buffer:\n");
674 //buffer_dump(utf8, 0);
675 #endif
676
677 return i;
678 }
679
680 // Read a null-terminated latin1 string, converting to UTF-8 in supplied buffer
681 // len_hint is the length of the latin1 string, utf8 may end up being larger
682 // or possibly less if we hit a null.
683 // Caller must manage utf8 buffer (init/free)
684 uint32_t
buffer_get_latin1_as_utf8(Buffer * buffer,Buffer * utf8,uint32_t len_hint)685 buffer_get_latin1_as_utf8(Buffer *buffer, Buffer *utf8, uint32_t len_hint)
686 {
687 int i = 0;
688 unsigned char *bptr = buffer_ptr(buffer);
689 uint8_t is_utf8;
690
691 if (!len_hint) return 0;
692
693 // We may get a valid UTF-8 string in here from ID3v1 or
694 // elsewhere, if so we don't want to translate from ISO-8859-1
695 is_utf8 = is_utf8_string(bptr, len_hint);
696
697 for (i = 0; i < len_hint; i++) {
698 uint8_t c = bptr[i];
699
700 if (is_utf8) {
701 buffer_put_char(utf8, c);
702 }
703 else {
704 // translate high chars from ISO-8859-1 to UTF-8
705 if (c < 0x80) {
706 buffer_put_char(utf8, c);
707 }
708 else if (c < 0xc0) {
709 buffer_put_char(utf8, 0xc2);
710 buffer_put_char(utf8, c);
711 }
712 else {
713 buffer_put_char(utf8, 0xc3);
714 buffer_put_char(utf8, c - 64);
715 }
716 }
717
718 if (c == 0) {
719 i++;
720 break;
721 }
722 }
723
724 // Consume string + null
725 buffer_consume(buffer, i);
726
727 // Add null if one wasn't provided
728 if ( (utf8->buf + utf8->end - 1)[0] != 0 ) {
729 buffer_put_char(utf8, 0);
730 }
731
732 #ifdef AUDIO_SCAN_DEBUG
733 //DEBUG_TRACE("utf8 buffer:\n");
734 //buffer_dump(utf8, 0);
735 #endif
736
737 return i;
738 }
739
740 // Read a null-terminated UTF-16 string, converting to UTF-8 in the supplied buffer
741 // Caller must manage utf8 buffer (init/free)
742 // XXX supports U+0000 ~ U+FFFF only.
743 uint32_t
buffer_get_utf16_as_utf8(Buffer * buffer,Buffer * utf8,uint32_t len,uint8_t byteorder)744 buffer_get_utf16_as_utf8(Buffer *buffer, Buffer *utf8, uint32_t len, uint8_t byteorder)
745 {
746 int i = 0;
747 uint16_t wc = 0;
748
749 if (!len) return 0;
750
751 for (i = 0; i < len; i += 2) {
752 // Check that we are not reading past the end of the buffer
753 if (len - i >= 2) {
754 wc = (byteorder == UTF16_BYTEORDER_LE)
755 ? buffer_get_short_le(buffer)
756 : buffer_get_short(buffer);
757 }
758 else {
759 DEBUG_TRACE(" UTF-16 text has an odd number of bytes, skipping final byte\n");
760 buffer_consume(buffer, 1);
761 wc = 0;
762 }
763
764 if (wc < 0x80) {
765 buffer_put_char(utf8, wc & 0xff);
766 }
767 else if (wc < 0x800) {
768 buffer_put_char(utf8, 0xc0 | (wc>>6));
769 buffer_put_char(utf8, 0x80 | (wc & 0x3f));
770 }
771 else {
772 buffer_put_char(utf8, 0xe0 | (wc>>12));
773 buffer_put_char(utf8, 0x80 | ((wc>>6) & 0x3f));
774 buffer_put_char(utf8, 0x80 | (wc & 0x3f));
775 }
776
777 if (wc == 0) {
778 i += 2;
779 break;
780 }
781 }
782
783 // Add null if one wasn't provided
784 if ( (utf8->buf + utf8->end - 1)[0] != 0 ) {
785 buffer_put_char(utf8, 0);
786 }
787
788 #ifdef AUDIO_SCAN_DEBUG
789 //DEBUG_TRACE("utf8 buffer:\n");
790 //buffer_dump(utf8, 0);
791 #endif
792
793 return i;
794 }
795
796 #ifdef HAS_GUID
797 void
buffer_get_guid(Buffer * buffer,GUID * g)798 buffer_get_guid(Buffer *buffer, GUID *g)
799 {
800 g->Data1 = buffer_get_int_le(buffer);
801 g->Data2 = buffer_get_short_le(buffer);
802 g->Data3 = buffer_get_short_le(buffer);
803
804 buffer_get(buffer, g->Data4, 8);
805 }
806 #endif
807
808 int
buffer_get_float32_le_ret(float * ret,Buffer * buffer)809 buffer_get_float32_le_ret(float *ret, Buffer *buffer)
810 {
811 u_char buf[4];
812
813 if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
814 return (-1);
815 *ret = get_f32le(buf);
816 return (0);
817 }
818
819 float
buffer_get_float32_le(Buffer * buffer)820 buffer_get_float32_le(Buffer *buffer)
821 {
822 float ret;
823
824 if (buffer_get_float32_le_ret(&ret, buffer) == -1)
825 croak("buffer_get_float32_le_ret: buffer error");
826
827 return (ret);
828 }
829
830 // From libsndfile
831 float
get_f32le(const void * vp)832 get_f32le(const void *vp)
833 {
834 const u_char *p = (const u_char *)vp;
835 float v;
836 int exponent, mantissa, negative;
837
838 negative = p[3] & 0x80;
839 exponent = ((p[3] & 0x7F) << 1) | ((p[2] & 0x80) ? 1 : 0);
840 mantissa = ((p[2] & 0x7F) << 16) | (p[1] << 8) | (p[0]);
841
842 if ( !(exponent || mantissa) ) {
843 return 0.0;
844 }
845
846 mantissa |= 0x800000;
847 exponent = exponent ? exponent - 127 : 0;
848
849 v = mantissa ? ((float)mantissa) / ((float)0x800000) : 0.0;
850
851 if (negative) {
852 v *= -1;
853 }
854
855 if (exponent > 0) {
856 v *= pow(2.0, exponent);
857 }
858 else if (exponent < 0) {
859 v /= pow(2.0, abs(exponent));
860 }
861
862 return (v);
863 }
864
865 int
buffer_get_float32_ret(float * ret,Buffer * buffer)866 buffer_get_float32_ret(float *ret, Buffer *buffer)
867 {
868 u_char buf[4];
869
870 if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
871 return (-1);
872 *ret = get_f32(buf);
873 return (0);
874 }
875
876 float
buffer_get_float32(Buffer * buffer)877 buffer_get_float32(Buffer *buffer)
878 {
879 float ret;
880
881 if (buffer_get_float32_ret(&ret, buffer) == -1)
882 croak("buffer_get_float32_ret: buffer error");
883
884 return (ret);
885 }
886
887 // From libsndfile
888 float
get_f32(const void * vp)889 get_f32(const void *vp)
890 {
891 const u_char *p = (const u_char *)vp;
892 float v;
893 int exponent, mantissa, negative;
894
895 negative = p[0] & 0x80;
896 exponent = ((p[0] & 0x7F) << 1) | ((p[1] & 0x80) ? 1 : 0);
897 mantissa = ((p[1] & 0x7F) << 16) | (p[2] << 8) | (p[3]);
898
899 if ( !(exponent || mantissa) ) {
900 return 0.0;
901 }
902
903 mantissa |= 0x800000;
904 exponent = exponent ? exponent - 127 : 0;
905
906 v = mantissa ? ((float)mantissa) / ((float)0x800000) : 0.0;
907
908 if (negative) {
909 v *= -1;
910 }
911
912 if (exponent > 0) {
913 v *= pow(2.0, exponent);
914 }
915 else if (exponent < 0) {
916 v /= pow(2.0, abs(exponent));
917 }
918
919 return (v);
920 }
921
922 // http://www.onicos.com/staff/iz/formats/aiff.html
923 // http://www.onicos.com/staff/iz/formats/ieee.c
924 double
buffer_get_ieee_float(Buffer * buffer)925 buffer_get_ieee_float(Buffer *buffer)
926 {
927 double f;
928 int expon;
929 unsigned long hiMant, loMant;
930
931 unsigned char *bptr = buffer_ptr(buffer);
932
933 expon = ((bptr[0] & 0x7F) << 8) | (bptr[1] & 0xFF);
934 hiMant = ((unsigned long)(bptr[2] & 0xFF) << 24)
935 | ((unsigned long)(bptr[3] & 0xFF) << 16)
936 | ((unsigned long)(bptr[4] & 0xFF) << 8)
937 | ((unsigned long)(bptr[5] & 0xFF));
938 loMant = ((unsigned long)(bptr[6] & 0xFF) << 24)
939 | ((unsigned long)(bptr[7] & 0xFF) << 16)
940 | ((unsigned long)(bptr[8] & 0xFF) << 8)
941 | ((unsigned long)(bptr[9] & 0xFF));
942
943 if (expon == 0 && hiMant == 0 && loMant == 0) {
944 f = 0;
945 }
946 else {
947 if (expon == 0x7FFF) { /* Infinity or NaN */
948 f = HUGE_VAL;
949 }
950 else {
951 expon -= 16383;
952 f = ldexp(UnsignedToFloat(hiMant), expon-=31);
953 f += ldexp(UnsignedToFloat(loMant), expon-=32);
954 }
955 }
956
957 buffer_consume(buffer, 10);
958
959 if (bptr[0] & 0x80)
960 return -f;
961 else
962 return f;
963 }
964
965 void
put_u16(void * vp,uint16_t v)966 put_u16(void *vp, uint16_t v)
967 {
968 u_char *p = (u_char *)vp;
969
970 p[0] = (u_char)(v >> 8) & 0xff;
971 p[1] = (u_char)v & 0xff;
972 }
973
974 void
put_u32(void * vp,uint32_t v)975 put_u32(void *vp, uint32_t v)
976 {
977 u_char *p = (u_char *)vp;
978
979 p[0] = (u_char)(v >> 24) & 0xff;
980 p[1] = (u_char)(v >> 16) & 0xff;
981 p[2] = (u_char)(v >> 8) & 0xff;
982 p[3] = (u_char)v & 0xff;
983 }
984
985 void
buffer_put_int(Buffer * buffer,u_int value)986 buffer_put_int(Buffer *buffer, u_int value)
987 {
988 char buf[4];
989
990 put_u32(buf, value);
991 buffer_append(buffer, buf, 4);
992 }
993
994 // Warnings:
995 // Do not request more than 32 bits at a time.
996 // Be careful if using other buffer functions without reading a multiple of 8 bits.
997 uint32_t
buffer_get_bits(Buffer * buffer,uint32_t bits)998 buffer_get_bits(Buffer *buffer, uint32_t bits)
999 {
1000 uint32_t mask = CacheMask[bits];
1001
1002 //PerlIO_printf(PerlIO_stderr(), "get_bits(%d), in cache %d\n", bits, buffer->ncached);
1003
1004 while (buffer->ncached < bits) {
1005 // Need to read more data
1006
1007 //PerlIO_printf(PerlIO_stderr(), "reading: ");
1008 //buffer_dump(buffer, 1);
1009
1010 buffer->cache = (buffer->cache << 8) | buffer_get_char(buffer);
1011 buffer->ncached += 8;
1012 }
1013
1014 buffer->ncached -= bits;
1015
1016 //PerlIO_printf(PerlIO_stderr(), "cache %x, ncached %d\n", buffer->cache, buffer->ncached);
1017 //PerlIO_printf(PerlIO_stderr(), "return %x\n", (buffer->cache >> buffer->ncached) & mask);
1018
1019 return (buffer->cache >> buffer->ncached) & mask;
1020 }
1021
1022 uint32_t
buffer_get_syncsafe(Buffer * buffer,uint8_t bytes)1023 buffer_get_syncsafe(Buffer *buffer, uint8_t bytes)
1024 {
1025 uint32_t value = 0;
1026 unsigned char *bptr = buffer_ptr(buffer);
1027
1028 switch (bytes) {
1029 case 5: value = (value << 4) | (*bptr++ & 0x0f);
1030 case 4: value = (value << 7) | (*bptr++ & 0x7f);
1031 value = (value << 7) | (*bptr++ & 0x7f);
1032 value = (value << 7) | (*bptr++ & 0x7f);
1033 value = (value << 7) | (*bptr++ & 0x7f);
1034 }
1035
1036 buffer_consume(buffer, bytes);
1037
1038 return value;
1039 }
1040