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