| 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 | 655 |  |  |  |  |  | buffer_init(Buffer *buffer, uint32_t len) | 
| 30 |  |  |  |  |  |  | { | 
| 31 | 655 | 100 |  |  |  |  | if (!len) len = BUFFER_ALLOCSZ; | 
| 32 |  |  |  |  |  |  |  | 
| 33 | 655 |  |  |  |  |  | buffer->alloc = 0; | 
| 34 | 655 |  |  |  |  |  | New(0, buffer->buf, (int)len, u_char); | 
| 35 | 655 |  |  |  |  |  | buffer->alloc = len; | 
| 36 | 655 |  |  |  |  |  | buffer->offset = 0; | 
| 37 | 655 |  |  |  |  |  | buffer->end = 0; | 
| 38 | 655 |  |  |  |  |  | buffer->cache = 0; | 
| 39 | 655 |  |  |  |  |  | buffer->ncached = 0; | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | #ifdef AUDIO_SCAN_DEBUG | 
| 42 |  |  |  |  |  |  | PerlIO_printf(PerlIO_stderr(), "Buffer allocated with %d bytes\n", len); | 
| 43 |  |  |  |  |  |  | #endif | 
| 44 | 655 |  |  |  |  |  | } | 
| 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 | 657 |  |  |  |  |  | buffer_free(Buffer *buffer) | 
| 63 |  |  |  |  |  |  | { | 
| 64 | 657 | 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 | 655 |  |  |  |  |  | memset(buffer->buf, 0, buffer->alloc); | 
| 69 | 655 |  |  |  |  |  | buffer->alloc = 0; | 
| 70 | 655 |  |  |  |  |  | Safefree(buffer->buf); | 
| 71 |  |  |  |  |  |  | } | 
| 72 | 657 |  |  |  |  |  | } | 
| 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 | 2328 |  |  |  |  |  | buffer_clear(Buffer *buffer) | 
| 81 |  |  |  |  |  |  | { | 
| 82 | 2328 |  |  |  |  |  | buffer->offset = 0; | 
| 83 | 2328 |  |  |  |  |  | buffer->end = 0; | 
| 84 | 2328 |  |  |  |  |  | buffer->cache = 0; | 
| 85 | 2328 |  |  |  |  |  | buffer->ncached = 0; | 
| 86 | 2328 |  |  |  |  |  | } | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | /* Appends data to the buffer, expanding it if necessary. */ | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | void | 
| 91 | 81962 |  |  |  |  |  | buffer_append(Buffer *buffer, const void *data, uint32_t len) | 
| 92 |  |  |  |  |  |  | { | 
| 93 |  |  |  |  |  |  | void *p; | 
| 94 | 81962 |  |  |  |  |  | p = buffer_append_space(buffer, len); | 
| 95 | 81962 |  |  |  |  |  | Copy(data, p, (int)len, u_char); | 
| 96 | 81962 |  |  |  |  |  | } | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | static int | 
| 99 | 419 |  |  |  |  |  | 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 | 419 | 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 | 316 |  |  |  |  |  | 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 | 82055 |  |  |  |  |  | buffer_append_space(Buffer *buffer, uint32_t len) | 
| 126 |  |  |  |  |  |  | { | 
| 127 |  |  |  |  |  |  | uint32_t newlen; | 
| 128 |  |  |  |  |  |  | void *p; | 
| 129 |  |  |  |  |  |  |  | 
| 130 | 82055 | 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 | 82055 | 100 |  |  |  |  | if (buffer->offset == buffer->end) { | 
| 135 | 2957 |  |  |  |  |  | buffer->offset = 0; | 
| 136 | 2957 |  |  |  |  |  | buffer->end = 0; | 
| 137 |  |  |  |  |  |  | } | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | restart: | 
| 140 |  |  |  |  |  |  | /* If there is enough space to store all data, store it now. */ | 
| 141 | 82474 | 100 |  |  |  |  | if (buffer->end + len <= buffer->alloc) { | 
| 142 | 82055 |  |  |  |  |  | p = buffer->buf + buffer->end; | 
| 143 | 82055 |  |  |  |  |  | buffer->end += len; | 
| 144 | 82055 |  |  |  |  |  | return p; | 
| 145 |  |  |  |  |  |  | } | 
| 146 |  |  |  |  |  |  |  | 
| 147 |  |  |  |  |  |  | /* Compact data back to the start of the buffer if necessary */ | 
| 148 | 419 | 100 |  |  |  |  | if (buffer_compact(buffer)) | 
| 149 | 103 |  |  |  |  |  | goto restart; | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | /* Increase the size of the buffer and retry. */ | 
| 152 | 316 | 100 |  |  |  |  | if (buffer->alloc + len < 4096) | 
| 153 | 129 |  |  |  |  |  | newlen = (buffer->alloc + len) * 2; | 
| 154 |  |  |  |  |  |  | else | 
| 155 | 187 |  |  |  |  |  | newlen = buffer->alloc + len + 4096; | 
| 156 |  |  |  |  |  |  |  | 
| 157 | 316 | 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 | 316 |  |  |  |  |  | Renew(buffer->buf, (int)newlen, u_char); | 
| 164 | 316 |  |  |  |  |  | buffer->alloc = newlen; | 
| 165 | 316 |  |  |  |  |  | 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 | 63018 |  |  |  |  |  | buffer_len(Buffer *buffer) | 
| 194 |  |  |  |  |  |  | { | 
| 195 | 63018 |  |  |  |  |  | return buffer->end - buffer->offset; | 
| 196 |  |  |  |  |  |  | } | 
| 197 |  |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | /* Gets data from the beginning of the buffer. */ | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | int | 
| 201 | 80685 |  |  |  |  |  | buffer_get_ret(Buffer *buffer, void *buf, uint32_t len) | 
| 202 |  |  |  |  |  |  | { | 
| 203 | 80685 | 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 | 80685 |  |  |  |  |  | Copy(buffer->buf + buffer->offset, buf, (int)len, char); | 
| 209 | 80685 |  |  |  |  |  | buffer->offset += len; | 
| 210 | 80685 |  |  |  |  |  | return (0); | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | void | 
| 214 | 1967 |  |  |  |  |  | buffer_get(Buffer *buffer, void *buf, uint32_t len) | 
| 215 |  |  |  |  |  |  | { | 
| 216 | 1967 | 50 |  |  |  |  | if (buffer_get_ret(buffer, buf, len) == -1) | 
| 217 | 0 |  |  |  |  |  | croak("buffer_get: buffer error"); | 
| 218 | 1967 |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | /* Consumes the given number of bytes from the beginning of the buffer. */ | 
| 221 |  |  |  |  |  |  |  | 
| 222 |  |  |  |  |  |  | int | 
| 223 | 56358 |  |  |  |  |  | buffer_consume_ret(Buffer *buffer, uint32_t bytes) | 
| 224 |  |  |  |  |  |  | { | 
| 225 | 56358 | 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 | 56358 |  |  |  |  |  | buffer->offset += bytes; | 
| 231 | 56358 |  |  |  |  |  | return (0); | 
| 232 |  |  |  |  |  |  | } | 
| 233 |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  | void | 
| 235 | 56358 |  |  |  |  |  | buffer_consume(Buffer *buffer, uint32_t bytes) | 
| 236 |  |  |  |  |  |  | { | 
| 237 | 56358 | 50 |  |  |  |  | if (buffer_consume_ret(buffer, bytes) == -1) | 
| 238 | 0 |  |  |  |  |  | croak("buffer_consume: buffer error"); | 
| 239 | 56358 |  |  |  |  |  | } | 
| 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 | 59808 |  |  |  |  |  | buffer_ptr(Buffer *buffer) | 
| 264 |  |  |  |  |  |  | { | 
| 265 | 59808 |  |  |  |  |  | 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 | 4051 |  |  |  |  |  | buffer_get_char_ret(char *ret, Buffer *buffer) | 
| 323 |  |  |  |  |  |  | { | 
| 324 | 4051 | 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 | 4051 |  |  |  |  |  | return (0); | 
| 330 |  |  |  |  |  |  | } | 
| 331 |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  | int | 
| 333 | 4051 |  |  |  |  |  | buffer_get_char(Buffer *buffer) | 
| 334 |  |  |  |  |  |  | { | 
| 335 |  |  |  |  |  |  | char ch; | 
| 336 |  |  |  |  |  |  |  | 
| 337 | 4051 | 50 |  |  |  |  | if (buffer_get_char_ret(&ch, buffer) == -1) | 
| 338 | 0 |  |  |  |  |  | croak("buffer_get_char: buffer error"); | 
| 339 | 4051 |  |  |  |  |  | return (u_char) ch; | 
| 340 |  |  |  |  |  |  | } | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  | uint32_t | 
| 343 | 2091 |  |  |  |  |  | get_u32le(const void *vp) | 
| 344 |  |  |  |  |  |  | { | 
| 345 | 2091 |  |  |  |  |  | const u_char *p = (const u_char *)vp; | 
| 346 |  |  |  |  |  |  | uint32_t v; | 
| 347 |  |  |  |  |  |  |  | 
| 348 | 2091 |  |  |  |  |  | v  = (uint32_t)p[3] << 24; | 
| 349 | 2091 |  |  |  |  |  | v |= (uint32_t)p[2] << 16; | 
| 350 | 2091 |  |  |  |  |  | v |= (uint32_t)p[1] << 8; | 
| 351 | 2091 |  |  |  |  |  | v |= (uint32_t)p[0]; | 
| 352 |  |  |  |  |  |  |  | 
| 353 | 2091 |  |  |  |  |  | return (v); | 
| 354 |  |  |  |  |  |  | } | 
| 355 |  |  |  |  |  |  |  | 
| 356 |  |  |  |  |  |  | int | 
| 357 | 2091 |  |  |  |  |  | buffer_get_int_le_ret(uint32_t *ret, Buffer *buffer) | 
| 358 |  |  |  |  |  |  | { | 
| 359 |  |  |  |  |  |  | u_char buf[4]; | 
| 360 |  |  |  |  |  |  |  | 
| 361 | 2091 | 50 |  |  |  |  | if (buffer_get_ret(buffer, (char *) buf, 4) == -1) | 
| 362 | 0 |  |  |  |  |  | return (-1); | 
| 363 | 2091 |  |  |  |  |  | *ret = get_u32le(buf); | 
| 364 | 2091 |  |  |  |  |  | return (0); | 
| 365 |  |  |  |  |  |  | } | 
| 366 |  |  |  |  |  |  |  | 
| 367 |  |  |  |  |  |  | uint32_t | 
| 368 | 2091 |  |  |  |  |  | buffer_get_int_le(Buffer *buffer) | 
| 369 |  |  |  |  |  |  | { | 
| 370 |  |  |  |  |  |  | uint32_t ret; | 
| 371 |  |  |  |  |  |  |  | 
| 372 | 2091 | 50 |  |  |  |  | if (buffer_get_int_le_ret(&ret, buffer) == -1) | 
| 373 | 0 |  |  |  |  |  | croak("buffer_get_int_le: buffer error"); | 
| 374 |  |  |  |  |  |  |  | 
| 375 | 2091 |  |  |  |  |  | return (ret); | 
| 376 |  |  |  |  |  |  | } | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | uint32_t | 
| 379 | 57219 |  |  |  |  |  | get_u32(const void *vp) | 
| 380 |  |  |  |  |  |  | { | 
| 381 | 57219 |  |  |  |  |  | const u_char *p = (const u_char *)vp; | 
| 382 |  |  |  |  |  |  | uint32_t v; | 
| 383 |  |  |  |  |  |  |  | 
| 384 | 57219 |  |  |  |  |  | v  = (uint32_t)p[0] << 24; | 
| 385 | 57219 |  |  |  |  |  | v |= (uint32_t)p[1] << 16; | 
| 386 | 57219 |  |  |  |  |  | v |= (uint32_t)p[2] << 8; | 
| 387 | 57219 |  |  |  |  |  | v |= (uint32_t)p[3]; | 
| 388 |  |  |  |  |  |  |  | 
| 389 | 57219 |  |  |  |  |  | return (v); | 
| 390 |  |  |  |  |  |  | } | 
| 391 |  |  |  |  |  |  |  | 
| 392 |  |  |  |  |  |  | int | 
| 393 | 57219 |  |  |  |  |  | buffer_get_int_ret(uint32_t *ret, Buffer *buffer) | 
| 394 |  |  |  |  |  |  | { | 
| 395 |  |  |  |  |  |  | u_char buf[4]; | 
| 396 |  |  |  |  |  |  |  | 
| 397 | 57219 | 50 |  |  |  |  | if (buffer_get_ret(buffer, (char *) buf, 4) == -1) | 
| 398 | 0 |  |  |  |  |  | return (-1); | 
| 399 | 57219 |  |  |  |  |  | *ret = get_u32(buf); | 
| 400 | 57219 |  |  |  |  |  | return (0); | 
| 401 |  |  |  |  |  |  | } | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | uint32_t | 
| 404 | 57219 |  |  |  |  |  | buffer_get_int(Buffer *buffer) | 
| 405 |  |  |  |  |  |  | { | 
| 406 |  |  |  |  |  |  | uint32_t ret; | 
| 407 |  |  |  |  |  |  |  | 
| 408 | 57219 | 50 |  |  |  |  | if (buffer_get_int_ret(&ret, buffer) == -1) | 
| 409 | 0 |  |  |  |  |  | croak("buffer_get_int: buffer error"); | 
| 410 |  |  |  |  |  |  |  | 
| 411 | 57219 |  |  |  |  |  | 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 | 643 |  |  |  |  |  | get_u64le(const void *vp) | 
| 486 |  |  |  |  |  |  | { | 
| 487 | 643 |  |  |  |  |  | const u_char *p = (const u_char *)vp; | 
| 488 |  |  |  |  |  |  | uint64_t v; | 
| 489 |  |  |  |  |  |  |  | 
| 490 | 643 |  |  |  |  |  | v  = (uint64_t)p[7] << 56; | 
| 491 | 643 |  |  |  |  |  | v |= (uint64_t)p[6] << 48; | 
| 492 | 643 |  |  |  |  |  | v |= (uint64_t)p[5] << 40; | 
| 493 | 643 |  |  |  |  |  | v |= (uint64_t)p[4] << 32; | 
| 494 | 643 |  |  |  |  |  | v |= (uint64_t)p[3] << 24; | 
| 495 | 643 |  |  |  |  |  | v |= (uint64_t)p[2] << 16; | 
| 496 | 643 |  |  |  |  |  | v |= (uint64_t)p[1] << 8; | 
| 497 | 643 |  |  |  |  |  | v |= (uint64_t)p[0]; | 
| 498 |  |  |  |  |  |  |  | 
| 499 | 643 |  |  |  |  |  | return (v); | 
| 500 |  |  |  |  |  |  | } | 
| 501 |  |  |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | int | 
| 503 | 643 |  |  |  |  |  | buffer_get_int64_le_ret(uint64_t *ret, Buffer *buffer) | 
| 504 |  |  |  |  |  |  | { | 
| 505 |  |  |  |  |  |  | u_char buf[8]; | 
| 506 |  |  |  |  |  |  |  | 
| 507 | 643 | 50 |  |  |  |  | if (buffer_get_ret(buffer, (char *) buf, 8) == -1) | 
| 508 | 0 |  |  |  |  |  | return (-1); | 
| 509 | 643 |  |  |  |  |  | *ret = get_u64le(buf); | 
| 510 | 643 |  |  |  |  |  | return (0); | 
| 511 |  |  |  |  |  |  | } | 
| 512 |  |  |  |  |  |  |  | 
| 513 |  |  |  |  |  |  | uint64_t | 
| 514 | 643 |  |  |  |  |  | buffer_get_int64_le(Buffer *buffer) | 
| 515 |  |  |  |  |  |  | { | 
| 516 |  |  |  |  |  |  | uint64_t ret; | 
| 517 |  |  |  |  |  |  |  | 
| 518 | 643 | 50 |  |  |  |  | if (buffer_get_int64_le_ret(&ret, buffer) == -1) | 
| 519 | 0 |  |  |  |  |  | croak("buffer_get_int64_le: buffer error"); | 
| 520 |  |  |  |  |  |  |  | 
| 521 | 643 |  |  |  |  |  | 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 | 1277 |  |  |  |  |  | get_u16(const void *vp) | 
| 600 |  |  |  |  |  |  | { | 
| 601 | 1277 |  |  |  |  |  | const u_char *p = (const u_char *)vp; | 
| 602 |  |  |  |  |  |  | uint16_t v; | 
| 603 |  |  |  |  |  |  |  | 
| 604 | 1277 |  |  |  |  |  | v  = (uint16_t)p[0] << 8; | 
| 605 | 1277 |  |  |  |  |  | v |= (uint16_t)p[1]; | 
| 606 |  |  |  |  |  |  |  | 
| 607 | 1277 |  |  |  |  |  | return (v); | 
| 608 |  |  |  |  |  |  | } | 
| 609 |  |  |  |  |  |  |  | 
| 610 |  |  |  |  |  |  | int | 
| 611 | 1277 |  |  |  |  |  | buffer_get_short_ret(uint16_t *ret, Buffer *buffer) | 
| 612 |  |  |  |  |  |  | { | 
| 613 |  |  |  |  |  |  | u_char buf[2]; | 
| 614 |  |  |  |  |  |  |  | 
| 615 | 1277 | 50 |  |  |  |  | if (buffer_get_ret(buffer, (char *) buf, 2) == -1) | 
| 616 | 0 |  |  |  |  |  | return (-1); | 
| 617 | 1277 |  |  |  |  |  | *ret = get_u16(buf); | 
| 618 | 1277 |  |  |  |  |  | return (0); | 
| 619 |  |  |  |  |  |  | } | 
| 620 |  |  |  |  |  |  |  | 
| 621 |  |  |  |  |  |  | uint16_t | 
| 622 | 1277 |  |  |  |  |  | buffer_get_short(Buffer *buffer) | 
| 623 |  |  |  |  |  |  | { | 
| 624 |  |  |  |  |  |  | uint16_t ret; | 
| 625 |  |  |  |  |  |  |  | 
| 626 | 1277 | 50 |  |  |  |  | if (buffer_get_short_ret(&ret, buffer) == -1) | 
| 627 | 0 |  |  |  |  |  | croak("buffer_get_short: buffer error"); | 
| 628 |  |  |  |  |  |  |  | 
| 629 | 1277 |  |  |  |  |  | return (ret); | 
| 630 |  |  |  |  |  |  | } | 
| 631 |  |  |  |  |  |  |  | 
| 632 |  |  |  |  |  |  | /* | 
| 633 |  |  |  |  |  |  | * Stores a character in the buffer. | 
| 634 |  |  |  |  |  |  | */ | 
| 635 |  |  |  |  |  |  | void | 
| 636 | 72923 |  |  |  |  |  | buffer_put_char(Buffer *buffer, int value) | 
| 637 |  |  |  |  |  |  | { | 
| 638 | 72923 |  |  |  |  |  | char ch = value; | 
| 639 |  |  |  |  |  |  |  | 
| 640 | 72923 |  |  |  |  |  | buffer_append(buffer, &ch, 1); | 
| 641 | 72923 |  |  |  |  |  | } | 
| 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 | 797 |  |  |  |  |  | buffer_get_latin1_as_utf8(Buffer *buffer, Buffer *utf8, uint32_t len_hint) | 
| 686 |  |  |  |  |  |  | { | 
| 687 | 797 |  |  |  |  |  | int i = 0; | 
| 688 | 797 |  |  |  |  |  | unsigned char *bptr = buffer_ptr(buffer); | 
| 689 |  |  |  |  |  |  | uint8_t is_utf8; | 
| 690 |  |  |  |  |  |  |  | 
| 691 | 797 | 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 | 797 |  |  |  |  |  | is_utf8 = is_utf8_string(bptr, len_hint); | 
| 696 |  |  |  |  |  |  |  | 
| 697 | 48976 | 100 |  |  |  |  | for (i = 0; i < len_hint; i++) { | 
| 698 | 48663 |  |  |  |  |  | uint8_t c = bptr[i]; | 
| 699 |  |  |  |  |  |  |  | 
| 700 | 48663 | 100 |  |  |  |  | if (is_utf8) { | 
| 701 | 36690 |  |  |  |  |  | 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 | 48663 | 100 |  |  |  |  | if (c == 0) { | 
| 719 | 484 |  |  |  |  |  | i++; | 
| 720 | 484 |  |  |  |  |  | break; | 
| 721 |  |  |  |  |  |  | } | 
| 722 |  |  |  |  |  |  | } | 
| 723 |  |  |  |  |  |  |  | 
| 724 |  |  |  |  |  |  | // Consume string + null | 
| 725 | 797 |  |  |  |  |  | buffer_consume(buffer, i); | 
| 726 |  |  |  |  |  |  |  | 
| 727 |  |  |  |  |  |  | // Add null if one wasn't provided | 
| 728 | 797 | 100 |  |  |  |  | if ( (utf8->buf + utf8->end - 1)[0] != 0 ) { | 
| 729 | 313 |  |  |  |  |  | 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 | 797 |  |  |  |  |  | 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 | 564 |  |  |  |  |  | buffer_get_syncsafe(Buffer *buffer, uint8_t bytes) | 
| 1024 |  |  |  |  |  |  | { | 
| 1025 | 564 |  |  |  |  |  | uint32_t value = 0; | 
| 1026 | 564 |  |  |  |  |  | unsigned char *bptr = buffer_ptr(buffer); | 
| 1027 |  |  |  |  |  |  |  | 
| 1028 | 564 |  |  |  |  |  | switch (bytes) { | 
| 1029 | 0 |  |  |  |  |  | case 5: value = (value << 4) | (*bptr++ & 0x0f); | 
| 1030 | 564 |  |  |  |  |  | case 4: value = (value << 7) | (*bptr++ & 0x7f); | 
| 1031 | 564 |  |  |  |  |  | value = (value << 7) | (*bptr++ & 0x7f); | 
| 1032 | 564 |  |  |  |  |  | value = (value << 7) | (*bptr++ & 0x7f); | 
| 1033 | 564 |  |  |  |  |  | value = (value << 7) | (*bptr++ & 0x7f); | 
| 1034 |  |  |  |  |  |  | } | 
| 1035 |  |  |  |  |  |  |  | 
| 1036 | 564 |  |  |  |  |  | buffer_consume(buffer, bytes); | 
| 1037 |  |  |  |  |  |  |  | 
| 1038 | 564 |  |  |  |  |  | return value; | 
| 1039 |  |  |  |  |  |  | } |