File Coverage

src/buffer.c
Criterion Covered Total %
statement 354 420 84.2
branch 97 162 59.8
condition n/a
subroutine n/a
pod n/a
total 451 582 77.4


line stmt bran cond sub pod time code
1             // Derived from:
2              
3             /* $OpenBSD: buffer.c,v 1.31 2006/08/03 03:34:41 deraadt Exp $ */
4             /*
5             * Author: Tatu Ylonen
6             * Copyright (c) 1995 Tatu Ylonen , 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
29 630           buffer_init(Buffer *buffer, uint32_t len)
30             {
31 630 100         if (!len) len = BUFFER_ALLOCSZ;
32              
33 630           buffer->alloc = 0;
34 630           New(0, buffer->buf, (int)len, u_char);
35 630           buffer->alloc = len;
36 630           buffer->offset = 0;
37 630           buffer->end = 0;
38 630           buffer->cache = 0;
39 630           buffer->ncached = 0;
40              
41             #ifdef AUDIO_SCAN_DEBUG
42             PerlIO_printf(PerlIO_stderr(), "Buffer allocated with %d bytes\n", len);
43             #endif
44 630           }
45              
46             /* Allows easy reuse of a buffer, will init or clear buffer if it already exists */
47              
48             void
49 240           buffer_init_or_clear(Buffer *buffer, uint32_t len)
50             {
51 240 100         if (!buffer->alloc) {
52 39           buffer_init(buffer, len);
53             }
54             else {
55 201           buffer_clear(buffer);
56             }
57 240           }
58              
59             /* Frees any memory used for the buffer. */
60              
61             void
62 632           buffer_free(Buffer *buffer)
63             {
64 632 100         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 630           memset(buffer->buf, 0, buffer->alloc);
69 630           buffer->alloc = 0;
70 630           Safefree(buffer->buf);
71             }
72 632           }
73              
74             /*
75             * Clears any data from the buffer, making it empty. This does not actually
76             * zero the memory.
77             */
78              
79             void
80 2292           buffer_clear(Buffer *buffer)
81             {
82 2292           buffer->offset = 0;
83 2292           buffer->end = 0;
84 2292           buffer->cache = 0;
85 2292           buffer->ncached = 0;
86 2292           }
87              
88             /* Appends data to the buffer, expanding it if necessary. */
89              
90             void
91 81869           buffer_append(Buffer *buffer, const void *data, uint32_t len)
92             {
93             void *p;
94 81869           p = buffer_append_space(buffer, len);
95 81869           Copy(data, p, (int)len, u_char);
96 81869           }
97              
98             static int
99 369           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 369 100         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 103           Move(buffer->buf + buffer->offset, buffer->buf, (int)(buffer->end - buffer->offset), u_char);
110 103           buffer->end -= buffer->offset;
111 103           buffer->offset = 0;
112 103           return (1);
113             }
114              
115 266           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 *
125 81891           buffer_append_space(Buffer *buffer, uint32_t len)
126             {
127             uint32_t newlen;
128             void *p;
129              
130 81891 50         if (len > BUFFER_MAX_CHUNK)
131 0           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 81891 100         if (buffer->offset == buffer->end) {
135 2911           buffer->offset = 0;
136 2911           buffer->end = 0;
137             }
138              
139             restart:
140             /* If there is enough space to store all data, store it now. */
141 82260 100         if (buffer->end + len <= buffer->alloc) {
142 81891           p = buffer->buf + buffer->end;
143 81891           buffer->end += len;
144 81891           return p;
145             }
146              
147             /* Compact data back to the start of the buffer if necessary */
148 369 100         if (buffer_compact(buffer))
149 103           goto restart;
150              
151             /* Increase the size of the buffer and retry. */
152 266 100         if (buffer->alloc + len < 4096)
153 129           newlen = (buffer->alloc + len) * 2;
154             else
155 137           newlen = buffer->alloc + len + 4096;
156              
157 266 50         if (newlen > BUFFER_MAX_LEN)
158 0           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 266           Renew(buffer->buf, (int)newlen, u_char);
164 266           buffer->alloc = newlen;
165 266           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
174 0           buffer_check_alloc(Buffer *buffer, uint32_t len)
175             {
176 0 0         if (buffer->offset == buffer->end) {
177 0           buffer->offset = 0;
178 0           buffer->end = 0;
179             }
180             restart:
181 0 0         if (buffer->end + len < buffer->alloc)
182 0           return (1);
183 0 0         if (buffer_compact(buffer))
184 0           goto restart;
185 0 0         if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN)
186 0           return (1);
187 0           return (0);
188             }
189              
190             /* Returns the number of bytes of data in the buffer. */
191              
192             uint32_t
193 62846           buffer_len(Buffer *buffer)
194             {
195 62846           return buffer->end - buffer->offset;
196             }
197              
198             /* Gets data from the beginning of the buffer. */
199              
200             int
201 80577           buffer_get_ret(Buffer *buffer, void *buf, uint32_t len)
202             {
203 80577 50         if (len > buffer->end - buffer->offset) {
204 0           warn("buffer_get_ret: trying to get more bytes %d than in buffer %d", len, buffer->end - buffer->offset);
205 0           return (-1);
206             }
207              
208 80577           Copy(buffer->buf + buffer->offset, buf, (int)len, char);
209 80577           buffer->offset += len;
210 80577           return (0);
211             }
212              
213             void
214 1928           buffer_get(Buffer *buffer, void *buf, uint32_t len)
215             {
216 1928 50         if (buffer_get_ret(buffer, buf, len) == -1)
217 0           croak("buffer_get: buffer error");
218 1928           }
219              
220             /* Consumes the given number of bytes from the beginning of the buffer. */
221              
222             int
223 56300           buffer_consume_ret(Buffer *buffer, uint32_t bytes)
224             {
225 56300 50         if (bytes > buffer->end - buffer->offset) {
226 0           warn("buffer_consume_ret: trying to get more bytes %d than in buffer %d", bytes, buffer->end - buffer->offset);
227 0           return (-1);
228             }
229              
230 56300           buffer->offset += bytes;
231 56300           return (0);
232             }
233              
234             void
235 56300           buffer_consume(Buffer *buffer, uint32_t bytes)
236             {
237 56300 50         if (buffer_consume_ret(buffer, bytes) == -1)
238 0           croak("buffer_consume: buffer error");
239 56300           }
240              
241             /* Consumes the given number of bytes from the end of the buffer. */
242              
243             int
244 0           buffer_consume_end_ret(Buffer *buffer, uint32_t bytes)
245             {
246 0 0         if (bytes > buffer->end - buffer->offset)
247 0           return (-1);
248              
249 0           buffer->end -= bytes;
250 0           return (0);
251             }
252              
253             void
254 0           buffer_consume_end(Buffer *buffer, uint32_t bytes)
255             {
256 0 0         if (buffer_consume_end_ret(buffer, bytes) == -1)
257 0           croak("buffer_consume_end: trying to get more bytes %d than in buffer %d", bytes, buffer->end - buffer->offset);
258 0           }
259              
260             /* Returns a pointer to the first used byte in the buffer. */
261              
262             void *
263 59648           buffer_ptr(Buffer *buffer)
264             {
265 59648           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
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
322 4027           buffer_get_char_ret(char *ret, Buffer *buffer)
323             {
324 4027 50         if (buffer_get_ret(buffer, ret, 1) == -1) {
325 0           warn("buffer_get_char_ret: buffer_get_ret failed");
326 0           return (-1);
327             }
328              
329 4027           return (0);
330             }
331              
332             int
333 4027           buffer_get_char(Buffer *buffer)
334             {
335             char ch;
336              
337 4027 50         if (buffer_get_char_ret(&ch, buffer) == -1)
338 0           croak("buffer_get_char: buffer error");
339 4027           return (u_char) ch;
340             }
341              
342             uint32_t
343 2066           get_u32le(const void *vp)
344             {
345 2066           const u_char *p = (const u_char *)vp;
346             uint32_t v;
347              
348 2066           v = (uint32_t)p[3] << 24;
349 2066           v |= (uint32_t)p[2] << 16;
350 2066           v |= (uint32_t)p[1] << 8;
351 2066           v |= (uint32_t)p[0];
352              
353 2066           return (v);
354             }
355              
356             int
357 2066           buffer_get_int_le_ret(uint32_t *ret, Buffer *buffer)
358             {
359             u_char buf[4];
360              
361 2066 50         if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
362 0           return (-1);
363 2066           *ret = get_u32le(buf);
364 2066           return (0);
365             }
366              
367             uint32_t
368 2066           buffer_get_int_le(Buffer *buffer)
369             {
370             uint32_t ret;
371              
372 2066 50         if (buffer_get_int_le_ret(&ret, buffer) == -1)
373 0           croak("buffer_get_int_le: buffer error");
374              
375 2066           return (ret);
376             }
377              
378             uint32_t
379 57212           get_u32(const void *vp)
380             {
381 57212           const u_char *p = (const u_char *)vp;
382             uint32_t v;
383              
384 57212           v = (uint32_t)p[0] << 24;
385 57212           v |= (uint32_t)p[1] << 16;
386 57212           v |= (uint32_t)p[2] << 8;
387 57212           v |= (uint32_t)p[3];
388              
389 57212           return (v);
390             }
391              
392             int
393 57212           buffer_get_int_ret(uint32_t *ret, Buffer *buffer)
394             {
395             u_char buf[4];
396              
397 57212 50         if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
398 0           return (-1);
399 57212           *ret = get_u32(buf);
400 57212           return (0);
401             }
402              
403             uint32_t
404 57212           buffer_get_int(Buffer *buffer)
405             {
406             uint32_t ret;
407              
408 57212 50         if (buffer_get_int_ret(&ret, buffer) == -1)
409 0           croak("buffer_get_int: buffer error");
410              
411 57212           return (ret);
412             }
413              
414             uint32_t
415 114           get_u24(const void *vp)
416             {
417 114           const u_char *p = (const u_char *)vp;
418             uint32_t v;
419              
420 114           v = (uint32_t)p[0] << 16;
421 114           v |= (uint32_t)p[1] << 8;
422 114           v |= (uint32_t)p[2];
423              
424 114           return (v);
425             }
426              
427             int
428 114           buffer_get_int24_ret(uint32_t *ret, Buffer *buffer)
429             {
430             u_char buf[3];
431              
432 114 50         if (buffer_get_ret(buffer, (char *) buf, 3) == -1)
433 0           return (-1);
434 114           *ret = get_u24(buf);
435 114           return (0);
436             }
437              
438             uint32_t
439 114           buffer_get_int24(Buffer *buffer)
440             {
441             uint32_t ret;
442              
443 114 50         if (buffer_get_int24_ret(&ret, buffer) == -1)
444 0           croak("buffer_get_int24: buffer error");
445              
446 114           return (ret);
447             }
448              
449             uint32_t
450 8           get_u24le(const void *vp)
451             {
452 8           const u_char *p = (const u_char *)vp;
453             uint32_t v;
454              
455 8           v = (uint32_t)p[2] << 16;
456 8           v |= (uint32_t)p[1] << 8;
457 8           v |= (uint32_t)p[0];
458              
459 8           return (v);
460             }
461              
462             int
463 8           buffer_get_int24_le_ret(uint32_t *ret, Buffer *buffer)
464             {
465             u_char buf[3];
466              
467 8 50         if (buffer_get_ret(buffer, (char *) buf, 3) == -1)
468 0           return (-1);
469 8           *ret = get_u24le(buf);
470 8           return (0);
471             }
472              
473             uint32_t
474 8           buffer_get_int24_le(Buffer *buffer)
475             {
476             uint32_t ret;
477              
478 8 50         if (buffer_get_int24_le_ret(&ret, buffer) == -1)
479 0           croak("buffer_get_int24_le: buffer error");
480              
481 8           return (ret);
482             }
483              
484             uint64_t
485 637           get_u64le(const void *vp)
486             {
487 637           const u_char *p = (const u_char *)vp;
488             uint64_t v;
489              
490 637           v = (uint64_t)p[7] << 56;
491 637           v |= (uint64_t)p[6] << 48;
492 637           v |= (uint64_t)p[5] << 40;
493 637           v |= (uint64_t)p[4] << 32;
494 637           v |= (uint64_t)p[3] << 24;
495 637           v |= (uint64_t)p[2] << 16;
496 637           v |= (uint64_t)p[1] << 8;
497 637           v |= (uint64_t)p[0];
498              
499 637           return (v);
500             }
501              
502             int
503 637           buffer_get_int64_le_ret(uint64_t *ret, Buffer *buffer)
504             {
505             u_char buf[8];
506              
507 637 50         if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
508 0           return (-1);
509 637           *ret = get_u64le(buf);
510 637           return (0);
511             }
512              
513             uint64_t
514 637           buffer_get_int64_le(Buffer *buffer)
515             {
516             uint64_t ret;
517              
518 637 50         if (buffer_get_int64_le_ret(&ret, buffer) == -1)
519 0           croak("buffer_get_int64_le: buffer error");
520              
521 637           return (ret);
522             }
523              
524             uint64_t
525 132           get_u64(const void *vp)
526             {
527 132           const u_char *p = (const u_char *)vp;
528             uint64_t v;
529              
530 132           v = (uint64_t)p[0] << 56;
531 132           v |= (uint64_t)p[1] << 48;
532 132           v |= (uint64_t)p[2] << 40;
533 132           v |= (uint64_t)p[3] << 32;
534 132           v |= (uint64_t)p[4] << 24;
535 132           v |= (uint64_t)p[5] << 16;
536 132           v |= (uint64_t)p[6] << 8;
537 132           v |= (uint64_t)p[7];
538              
539 132           return (v);
540             }
541              
542             int
543 132           buffer_get_int64_ret(uint64_t *ret, Buffer *buffer)
544             {
545             u_char buf[8];
546              
547 132 50         if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
548 0           return (-1);
549 132           *ret = get_u64(buf);
550 132           return (0);
551             }
552              
553             uint64_t
554 132           buffer_get_int64(Buffer *buffer)
555             {
556             uint64_t ret;
557              
558 132 50         if (buffer_get_int64_ret(&ret, buffer) == -1)
559 0           croak("buffer_get_int64_le: buffer error");
560              
561 132           return (ret);
562             }
563              
564             uint16_t
565 13174           get_u16le(const void *vp)
566             {
567 13174           const u_char *p = (const u_char *)vp;
568             uint16_t v;
569              
570 13174           v = (uint16_t)p[1] << 8;
571 13174           v |= (uint16_t)p[0];
572              
573 13174           return (v);
574             }
575              
576             int
577 13174           buffer_get_short_le_ret(uint16_t *ret, Buffer *buffer)
578             {
579             u_char buf[2];
580              
581 13174 50         if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
582 0           return (-1);
583 13174           *ret = get_u16le(buf);
584 13174           return (0);
585             }
586              
587             uint16_t
588 13174           buffer_get_short_le(Buffer *buffer)
589             {
590             uint16_t ret;
591              
592 13174 50         if (buffer_get_short_le_ret(&ret, buffer) == -1)
593 0           croak("buffer_get_short_le: buffer error");
594              
595 13174           return (ret);
596             }
597              
598             uint16_t
599 1270           get_u16(const void *vp)
600             {
601 1270           const u_char *p = (const u_char *)vp;
602             uint16_t v;
603              
604 1270           v = (uint16_t)p[0] << 8;
605 1270           v |= (uint16_t)p[1];
606              
607 1270           return (v);
608             }
609              
610             int
611 1270           buffer_get_short_ret(uint16_t *ret, Buffer *buffer)
612             {
613             u_char buf[2];
614              
615 1270 50         if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
616 0           return (-1);
617 1270           *ret = get_u16(buf);
618 1270           return (0);
619             }
620              
621             uint16_t
622 1270           buffer_get_short(Buffer *buffer)
623             {
624             uint16_t ret;
625              
626 1270 50         if (buffer_get_short_ret(&ret, buffer) == -1)
627 0           croak("buffer_get_short: buffer error");
628              
629 1270           return (ret);
630             }
631              
632             /*
633             * Stores a character in the buffer.
634             */
635             void
636 72862           buffer_put_char(Buffer *buffer, int value)
637             {
638 72862           char ch = value;
639              
640 72862           buffer_append(buffer, &ch, 1);
641 72862           }
642              
643             // Read a null-terminated UTF-8 string
644             // Caller must manage utf8 buffer (init/free)
645             uint32_t
646 320           buffer_get_utf8(Buffer *buffer, Buffer *utf8, uint32_t len_hint)
647             {
648 320           int i = 0;
649 320           unsigned char *bptr = buffer_ptr(buffer);
650              
651 320 50         if (!len_hint) return 0;
652              
653 7580 100         for (i = 0; i < len_hint; i++) {
654 7407           uint8_t c = bptr[i];
655              
656 7407           buffer_put_char(utf8, c);
657              
658 7407 100         if (c == 0) {
659 147           i++;
660 147           break;
661             }
662             }
663              
664             // Consume string + null
665 320           buffer_consume(buffer, i);
666              
667             // Add null if one wasn't provided
668 320 100         if ( (utf8->buf + utf8->end - 1)[0] != 0 ) {
669 173           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 320           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
685 790           buffer_get_latin1_as_utf8(Buffer *buffer, Buffer *utf8, uint32_t len_hint)
686             {
687 790           int i = 0;
688 790           unsigned char *bptr = buffer_ptr(buffer);
689             uint8_t is_utf8;
690              
691 790 50         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 790           is_utf8 = is_utf8_string(bptr, len_hint);
696              
697 48915 100         for (i = 0; i < len_hint; i++) {
698 48609           uint8_t c = bptr[i];
699              
700 48609 100         if (is_utf8) {
701 36636           buffer_put_char(utf8, c);
702             }
703             else {
704             // translate high chars from ISO-8859-1 to UTF-8
705 11973 100         if (c < 0x80) {
706 6642           buffer_put_char(utf8, c);
707             }
708 5331 100         else if (c < 0xc0) {
709 5           buffer_put_char(utf8, 0xc2);
710 5           buffer_put_char(utf8, c);
711             }
712             else {
713 5326           buffer_put_char(utf8, 0xc3);
714 5326           buffer_put_char(utf8, c - 64);
715             }
716             }
717              
718 48609 100         if (c == 0) {
719 484           i++;
720 484           break;
721             }
722             }
723              
724             // Consume string + null
725 790           buffer_consume(buffer, i);
726              
727             // Add null if one wasn't provided
728 790 100         if ( (utf8->buf + utf8->end - 1)[0] != 0 ) {
729 306           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 790           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
744 709           buffer_get_utf16_as_utf8(Buffer *buffer, Buffer *utf8, uint32_t len, uint8_t byteorder)
745             {
746 709           int i = 0;
747 709           uint16_t wc = 0;
748              
749 709 100         if (!len) return 0;
750              
751 10962 100         for (i = 0; i < len; i += 2) {
752             // Check that we are not reading past the end of the buffer
753 10879 100         if (len - i >= 2) {
754 10878 100         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 1           buffer_consume(buffer, 1);
761 1           wc = 0;
762             }
763              
764 10879 100         if (wc < 0x80) {
765 10807           buffer_put_char(utf8, wc & 0xff);
766             }
767 72 100         else if (wc < 0x800) {
768 70           buffer_put_char(utf8, 0xc0 | (wc>>6));
769 70           buffer_put_char(utf8, 0x80 | (wc & 0x3f));
770             }
771             else {
772 2           buffer_put_char(utf8, 0xe0 | (wc>>12));
773 2           buffer_put_char(utf8, 0x80 | ((wc>>6) & 0x3f));
774 2           buffer_put_char(utf8, 0x80 | (wc & 0x3f));
775             }
776              
777 10879 100         if (wc == 0) {
778 622           i += 2;
779 622           break;
780             }
781             }
782              
783             // Add null if one wasn't provided
784 705 100         if ( (utf8->buf + utf8->end - 1)[0] != 0 ) {
785 83           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 705           return i;
794             }
795              
796             #ifdef HAS_GUID
797             void
798 454           buffer_get_guid(Buffer *buffer, GUID *g)
799             {
800 454           g->Data1 = buffer_get_int_le(buffer);
801 454           g->Data2 = buffer_get_short_le(buffer);
802 454           g->Data3 = buffer_get_short_le(buffer);
803              
804 454           buffer_get(buffer, g->Data4, 8);
805 454           }
806             #endif
807              
808             int
809 6           buffer_get_float32_le_ret(float *ret, Buffer *buffer)
810             {
811             u_char buf[4];
812              
813 6 50         if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
814 0           return (-1);
815 6           *ret = get_f32le(buf);
816 6           return (0);
817             }
818              
819             float
820 6           buffer_get_float32_le(Buffer *buffer)
821             {
822             float ret;
823              
824 6 50         if (buffer_get_float32_le_ret(&ret, buffer) == -1)
825 0           croak("buffer_get_float32_le_ret: buffer error");
826              
827 6           return (ret);
828             }
829              
830             // From libsndfile
831             float
832 6           get_f32le(const void *vp)
833             {
834 6           const u_char *p = (const u_char *)vp;
835             float v;
836             int exponent, mantissa, negative;
837              
838 6           negative = p[3] & 0x80;
839 6           exponent = ((p[3] & 0x7F) << 1) | ((p[2] & 0x80) ? 1 : 0);
840 6           mantissa = ((p[2] & 0x7F) << 16) | (p[1] << 8) | (p[0]);
841              
842 6 50         if ( !(exponent || mantissa) ) {
    0          
843 0           return 0.0;
844             }
845              
846 6           mantissa |= 0x800000;
847 6 50         exponent = exponent ? exponent - 127 : 0;
848              
849 6 50         v = mantissa ? ((float)mantissa) / ((float)0x800000) : 0.0;
850              
851 6 50         if (negative) {
852 0           v *= -1;
853             }
854              
855 6 50         if (exponent > 0) {
856 0           v *= pow(2.0, exponent);
857             }
858 6 50         else if (exponent < 0) {
859 6           v /= pow(2.0, abs(exponent));
860             }
861              
862 6           return (v);
863             }
864              
865             int
866 3           buffer_get_float32_ret(float *ret, Buffer *buffer)
867             {
868             u_char buf[4];
869              
870 3 50         if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
871 0           return (-1);
872 3           *ret = get_f32(buf);
873 3           return (0);
874             }
875              
876             float
877 3           buffer_get_float32(Buffer *buffer)
878             {
879             float ret;
880              
881 3 50         if (buffer_get_float32_ret(&ret, buffer) == -1)
882 0           croak("buffer_get_float32_ret: buffer error");
883              
884 3           return (ret);
885             }
886              
887             // From libsndfile
888             float
889 3           get_f32(const void *vp)
890             {
891 3           const u_char *p = (const u_char *)vp;
892             float v;
893             int exponent, mantissa, negative;
894              
895 3           negative = p[0] & 0x80;
896 3           exponent = ((p[0] & 0x7F) << 1) | ((p[1] & 0x80) ? 1 : 0);
897 3           mantissa = ((p[1] & 0x7F) << 16) | (p[2] << 8) | (p[3]);
898              
899 3 50         if ( !(exponent || mantissa) ) {
    0          
900 0           return 0.0;
901             }
902              
903 3           mantissa |= 0x800000;
904 3 50         exponent = exponent ? exponent - 127 : 0;
905              
906 3 50         v = mantissa ? ((float)mantissa) / ((float)0x800000) : 0.0;
907              
908 3 50         if (negative) {
909 0           v *= -1;
910             }
911              
912 3 50         if (exponent > 0) {
913 0           v *= pow(2.0, exponent);
914             }
915 3 50         else if (exponent < 0) {
916 3           v /= pow(2.0, abs(exponent));
917             }
918              
919 3           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
925 3           buffer_get_ieee_float(Buffer *buffer)
926             {
927             double f;
928             int expon;
929             unsigned long hiMant, loMant;
930              
931 3           unsigned char *bptr = buffer_ptr(buffer);
932              
933 3           expon = ((bptr[0] & 0x7F) << 8) | (bptr[1] & 0xFF);
934 6           hiMant = ((unsigned long)(bptr[2] & 0xFF) << 24)
935 3           | ((unsigned long)(bptr[3] & 0xFF) << 16)
936 3           | ((unsigned long)(bptr[4] & 0xFF) << 8)
937 3           | ((unsigned long)(bptr[5] & 0xFF));
938 6           loMant = ((unsigned long)(bptr[6] & 0xFF) << 24)
939 3           | ((unsigned long)(bptr[7] & 0xFF) << 16)
940 3           | ((unsigned long)(bptr[8] & 0xFF) << 8)
941 3           | ((unsigned long)(bptr[9] & 0xFF));
942              
943 3 50         if (expon == 0 && hiMant == 0 && loMant == 0) {
    0          
    0          
944 0           f = 0;
945             }
946             else {
947 3 50         if (expon == 0x7FFF) { /* Infinity or NaN */
948 0           f = HUGE_VAL;
949             }
950             else {
951 3           expon -= 16383;
952 3           f = ldexp(UnsignedToFloat(hiMant), expon-=31);
953 3           f += ldexp(UnsignedToFloat(loMant), expon-=32);
954             }
955             }
956              
957 3           buffer_consume(buffer, 10);
958              
959 3 50         if (bptr[0] & 0x80)
960 0           return -f;
961             else
962 3           return f;
963             }
964              
965             void
966 0           put_u16(void *vp, uint16_t v)
967             {
968 0           u_char *p = (u_char *)vp;
969              
970 0           p[0] = (u_char)(v >> 8) & 0xff;
971 0           p[1] = (u_char)v & 0xff;
972 0           }
973              
974             void
975 7763           put_u32(void *vp, uint32_t v)
976             {
977 7763           u_char *p = (u_char *)vp;
978              
979 7763           p[0] = (u_char)(v >> 24) & 0xff;
980 7763           p[1] = (u_char)(v >> 16) & 0xff;
981 7763           p[2] = (u_char)(v >> 8) & 0xff;
982 7763           p[3] = (u_char)v & 0xff;
983 7763           }
984              
985             void
986 7660           buffer_put_int(Buffer *buffer, u_int value)
987             {
988             char buf[4];
989              
990 7660           put_u32(buf, value);
991 7660           buffer_append(buffer, buf, 4);
992 7660           }
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
998 93           buffer_get_bits(Buffer *buffer, uint32_t bits)
999             {
1000 93           uint32_t mask = CacheMask[bits];
1001              
1002             //PerlIO_printf(PerlIO_stderr(), "get_bits(%d), in cache %d\n", bits, buffer->ncached);
1003              
1004 149 100         while (buffer->ncached < bits) {
1005             // Need to read more data
1006              
1007             //PerlIO_printf(PerlIO_stderr(), "reading: ");
1008             //buffer_dump(buffer, 1);
1009              
1010 56           buffer->cache = (buffer->cache << 8) | buffer_get_char(buffer);
1011 56           buffer->ncached += 8;
1012             }
1013              
1014 93           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 93           return (buffer->cache >> buffer->ncached) & mask;
1020             }
1021              
1022             uint32_t
1023 563           buffer_get_syncsafe(Buffer *buffer, uint8_t bytes)
1024             {
1025 563           uint32_t value = 0;
1026 563           unsigned char *bptr = buffer_ptr(buffer);
1027              
1028 563           switch (bytes) {
1029 0           case 5: value = (value << 4) | (*bptr++ & 0x0f);
1030 563           case 4: value = (value << 7) | (*bptr++ & 0x7f);
1031 563           value = (value << 7) | (*bptr++ & 0x7f);
1032 563           value = (value << 7) | (*bptr++ & 0x7f);
1033 563           value = (value << 7) | (*bptr++ & 0x7f);
1034             }
1035              
1036 563           buffer_consume(buffer, bytes);
1037              
1038 563           return value;
1039             }