summaryrefslogtreecommitdiff
path: root/thirdparty/misc
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/misc')
-rw-r--r--thirdparty/misc/curl_hostcheck.c217
-rw-r--r--thirdparty/misc/curl_hostcheck.h39
-rw-r--r--thirdparty/misc/fastlz.c796
-rw-r--r--thirdparty/misc/fastlz.h60
-rw-r--r--thirdparty/misc/stb_vorbis.c219
5 files changed, 583 insertions, 748 deletions
diff --git a/thirdparty/misc/curl_hostcheck.c b/thirdparty/misc/curl_hostcheck.c
deleted file mode 100644
index feef232619..0000000000
--- a/thirdparty/misc/curl_hostcheck.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-/* This file is an amalgamation of hostcheck.c and most of rawstr.c
- from cURL. The contents of the COPYING file mentioned above are:
-
-COPYRIGHT AND PERMISSION NOTICE
-
-Copyright (c) 1996 - 2013, Daniel Stenberg, <daniel@haxx.se>.
-
-All rights reserved.
-
-Permission to use, copy, modify, and distribute this software for any purpose
-with or without fee is hereby granted, provided that the above copyright
-notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
-NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
-OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of a copyright holder shall not
-be used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization of the copyright holder.
-*/
-
-#include "curl_hostcheck.h"
-#include <string.h>
-
-/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
- its behavior is altered by the current locale. */
-static char Curl_raw_toupper(char in)
-{
- switch (in) {
- case 'a':
- return 'A';
- case 'b':
- return 'B';
- case 'c':
- return 'C';
- case 'd':
- return 'D';
- case 'e':
- return 'E';
- case 'f':
- return 'F';
- case 'g':
- return 'G';
- case 'h':
- return 'H';
- case 'i':
- return 'I';
- case 'j':
- return 'J';
- case 'k':
- return 'K';
- case 'l':
- return 'L';
- case 'm':
- return 'M';
- case 'n':
- return 'N';
- case 'o':
- return 'O';
- case 'p':
- return 'P';
- case 'q':
- return 'Q';
- case 'r':
- return 'R';
- case 's':
- return 'S';
- case 't':
- return 'T';
- case 'u':
- return 'U';
- case 'v':
- return 'V';
- case 'w':
- return 'W';
- case 'x':
- return 'X';
- case 'y':
- return 'Y';
- case 'z':
- return 'Z';
- }
- return in;
-}
-
-/*
- * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant
- * to be locale independent and only compare strings we know are safe for
- * this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
- * some further explanation to why this function is necessary.
- *
- * The function is capable of comparing a-z case insensitively even for
- * non-ascii.
- */
-
-static int Curl_raw_equal(const char *first, const char *second)
-{
- while(*first && *second) {
- if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
- /* get out of the loop as soon as they don't match */
- break;
- first++;
- second++;
- }
- /* we do the comparison here (possibly again), just to make sure that if the
- loop above is skipped because one of the strings reached zero, we must not
- return this as a successful match */
- return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
-}
-
-static int Curl_raw_nequal(const char *first, const char *second, size_t max)
-{
- while(*first && *second && max) {
- if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
- break;
- }
- max--;
- first++;
- second++;
- }
- if(0 == max)
- return 1; /* they are equal this far */
-
- return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
-}
-
-/*
- * Match a hostname against a wildcard pattern.
- * E.g.
- * "foo.host.com" matches "*.host.com".
- *
- * We use the matching rule described in RFC6125, section 6.4.3.
- * http://tools.ietf.org/html/rfc6125#section-6.4.3
- */
-
-static int hostmatch(const char *hostname, const char *pattern)
-{
- const char *pattern_label_end, *pattern_wildcard, *hostname_label_end;
- int wildcard_enabled;
- size_t prefixlen, suffixlen;
- pattern_wildcard = strchr(pattern, '*');
- if(pattern_wildcard == NULL)
- return Curl_raw_equal(pattern, hostname) ?
- CURL_HOST_MATCH : CURL_HOST_NOMATCH;
-
- /* We require at least 2 dots in pattern to avoid too wide wildcard
- match. */
- wildcard_enabled = 1;
- pattern_label_end = strchr(pattern, '.');
- if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL ||
- pattern_wildcard > pattern_label_end ||
- Curl_raw_nequal(pattern, "xn--", 4)) {
- wildcard_enabled = 0;
- }
- if(!wildcard_enabled)
- return Curl_raw_equal(pattern, hostname) ?
- CURL_HOST_MATCH : CURL_HOST_NOMATCH;
-
- hostname_label_end = strchr(hostname, '.');
- if(hostname_label_end == NULL ||
- !Curl_raw_equal(pattern_label_end, hostname_label_end))
- return CURL_HOST_NOMATCH;
-
- /* The wildcard must match at least one character, so the left-most
- label of the hostname is at least as large as the left-most label
- of the pattern. */
- if(hostname_label_end - hostname < pattern_label_end - pattern)
- return CURL_HOST_NOMATCH;
-
- prefixlen = pattern_wildcard - pattern;
- suffixlen = pattern_label_end - (pattern_wildcard+1);
- return Curl_raw_nequal(pattern, hostname, prefixlen) &&
- Curl_raw_nequal(pattern_wildcard+1, hostname_label_end - suffixlen,
- suffixlen) ?
- CURL_HOST_MATCH : CURL_HOST_NOMATCH;
-}
-
-int Tool_Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
-{
- if(!match_pattern || !*match_pattern ||
- !hostname || !*hostname) /* sanity check */
- return 0;
-
- if(Curl_raw_equal(hostname, match_pattern)) /* trivial case */
- return 1;
-
- if(hostmatch(hostname,match_pattern) == CURL_HOST_MATCH)
- return 1;
- return 0;
-}
diff --git a/thirdparty/misc/curl_hostcheck.h b/thirdparty/misc/curl_hostcheck.h
deleted file mode 100644
index 1b7fbe81e3..0000000000
--- a/thirdparty/misc/curl_hostcheck.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef HEADER_TOOL_CURL_HOSTCHECK_H
-#define HEADER_TOOL_CURL_HOSTCHECK_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#define CURL_HOST_NOMATCH 0
-#define CURL_HOST_MATCH 1
-int Tool_Curl_cert_hostcheck(const char *match_pattern, const char *hostname);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HEADER_CURL_HOSTCHECK_H */
-
diff --git a/thirdparty/misc/fastlz.c b/thirdparty/misc/fastlz.c
index 508f6ea2ae..b4d2dd3c29 100644
--- a/thirdparty/misc/fastlz.c
+++ b/thirdparty/misc/fastlz.c
@@ -1,9 +1,6 @@
- /*
- FastLZ - lightning-fast lossless compression library
-
- Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
- Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
- Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+/*
+ FastLZ - Byte-aligned LZ77 compression library
+ Copyright (C) 2005-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -24,239 +21,375 @@
THE SOFTWARE.
*/
-#if !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
+#include "fastlz.h"
+
+#include <stdint.h>
/*
* Always check for bound when decompressing.
* Generally it is best to leave it defined.
*/
#define FASTLZ_SAFE
+#if defined(FASTLZ_USE_SAFE_DECOMPRESSOR) && (FASTLZ_USE_SAFE_DECOMPRESSOR == 0)
+#undef FASTLZ_SAFE
+#endif
/*
* Give hints to the compiler for branch prediction optimization.
*/
-#if defined(__GNUC__) && (__GNUC__ > 2)
-#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
-#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
+#define FASTLZ_LIKELY(c) (__builtin_expect(!!(c), 1))
+#define FASTLZ_UNLIKELY(c) (__builtin_expect(!!(c), 0))
#else
-#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
-#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
+#define FASTLZ_LIKELY(c) (c)
+#define FASTLZ_UNLIKELY(c) (c)
#endif
-/*
- * Use inlined functions for supported systems.
- */
-#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
-#define FASTLZ_INLINE inline
-#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
-#define FASTLZ_INLINE __inline
-#else
-#define FASTLZ_INLINE
+#if defined(FASTLZ_SAFE)
+#define FASTLZ_BOUND_CHECK(cond) \
+ if (FASTLZ_UNLIKELY(!(cond))) return 0;
+#else
+#define FASTLZ_BOUND_CHECK(cond) \
+ do { \
+ } while (0)
#endif
-/*
- * Prevent accessing more than 8-bit at once, except on x86 architectures.
- */
-#if !defined(FASTLZ_STRICT_ALIGN)
-#define FASTLZ_STRICT_ALIGN
-#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
-#undef FASTLZ_STRICT_ALIGN
-#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */
-#undef FASTLZ_STRICT_ALIGN
-#elif defined(_M_IX86) /* Intel, MSVC */
-#undef FASTLZ_STRICT_ALIGN
-#elif defined(__386)
-#undef FASTLZ_STRICT_ALIGN
-#elif defined(_X86_) /* MinGW */
-#undef FASTLZ_STRICT_ALIGN
-#elif defined(__I86__) /* Digital Mars */
-#undef FASTLZ_STRICT_ALIGN
-#endif
-#endif
+#define MAX_COPY 32
+#define MAX_LEN 264 /* 256 + 8 */
+#define MAX_L1_DISTANCE 8192
+#define MAX_L2_DISTANCE 8191
+#define MAX_FARDISTANCE (65535 + MAX_L2_DISTANCE - 1)
+
+#define FASTLZ_READU16(p) ((p)[0] | (p)[1] << 8)
+
+#define HASH_LOG 13
+#define HASH_SIZE (1 << HASH_LOG)
+#define HASH_MASK (HASH_SIZE - 1)
+#define HASH_FUNCTION(v, p) \
+ { \
+ v = FASTLZ_READU16(p); \
+ v ^= FASTLZ_READU16(p + 1) ^ (v >> (16 - HASH_LOG)); \
+ v &= HASH_MASK; \
+ }
-/*
- * FIXME: use preprocessor magic to set this on different platforms!
- */
-typedef unsigned char flzuint8;
-typedef unsigned short flzuint16;
-typedef unsigned int flzuint32;
+int fastlz1_compress(const void* input, int length, void* output) {
+ const uint8_t* ip = (const uint8_t*)input;
+ const uint8_t* ip_bound = ip + length - 2;
+ const uint8_t* ip_limit = ip + length - 12 - 1;
+ uint8_t* op = (uint8_t*)output;
-/* prototypes */
-int fastlz_compress(const void* input, int length, void* output);
-int fastlz_compress_level(int level, const void* input, int length, void* output);
-int fastlz_decompress(const void* input, int length, void* output, int maxout);
+ const uint8_t* htab[HASH_SIZE];
+ uint32_t hval;
-#define MAX_COPY 32
-#define MAX_LEN 264 /* 256 + 8 */
-#define MAX_DISTANCE 8192
+ uint32_t copy;
-#if !defined(FASTLZ_STRICT_ALIGN)
-#define FASTLZ_READU16(p) *((const flzuint16*)(p))
-#else
-#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
-#endif
+ /* sanity check */
+ if (FASTLZ_UNLIKELY(length < 4)) {
+ if (length) {
+ /* create literal copy only */
+ *op++ = length - 1;
+ ip_bound++;
+ while (ip <= ip_bound) *op++ = *ip++;
+ return length + 1;
+ } else
+ return 0;
+ }
-#define HASH_LOG 13
-#define HASH_SIZE (1<< HASH_LOG)
-#define HASH_MASK (HASH_SIZE-1)
-#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
-
-#undef FASTLZ_LEVEL
-#define FASTLZ_LEVEL 1
-
-#undef FASTLZ_COMPRESSOR
-#undef FASTLZ_DECOMPRESSOR
-#define FASTLZ_COMPRESSOR fastlz1_compress
-#define FASTLZ_DECOMPRESSOR fastlz1_decompress
-static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
-static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
-#include "fastlz.c"
-
-#undef FASTLZ_LEVEL
-#define FASTLZ_LEVEL 2
-
-#undef MAX_DISTANCE
-#define MAX_DISTANCE 8191
-#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
-
-#undef FASTLZ_COMPRESSOR
-#undef FASTLZ_DECOMPRESSOR
-#define FASTLZ_COMPRESSOR fastlz2_compress
-#define FASTLZ_DECOMPRESSOR fastlz2_decompress
-static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
-static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
-#include "fastlz.c"
-
-int fastlz_compress(const void* input, int length, void* output)
-{
- /* for short block, choose fastlz1 */
- if(length < 65536)
- return fastlz1_compress(input, length, output);
+ /* initializes hash table */
+ for (hval = 0; hval < HASH_SIZE; ++hval) htab[hval] = ip;
- /* else... */
- return fastlz2_compress(input, length, output);
+ /* we start with literal copy */
+ copy = 2;
+ *op++ = MAX_COPY - 1;
+ *op++ = *ip++;
+ *op++ = *ip++;
+
+ /* main loop */
+ while (FASTLZ_LIKELY(ip < ip_limit)) {
+ const uint8_t* ref;
+ uint32_t distance;
+
+ /* minimum match length */
+ uint32_t len = 3;
+
+ /* comparison starting-point */
+ const uint8_t* anchor = ip;
+
+ /* find potential match */
+ HASH_FUNCTION(hval, ip);
+ ref = htab[hval];
+
+ /* update hash table */
+ htab[hval] = anchor;
+
+ /* calculate distance to the match */
+ distance = anchor - ref;
+
+ /* is this a match? check the first 3 bytes */
+ if (distance == 0 || (distance >= MAX_L1_DISTANCE) || *ref++ != *ip++ ||
+ *ref++ != *ip++ || *ref++ != *ip++)
+ goto literal;
+
+ /* last matched byte */
+ ip = anchor + len;
+
+ /* distance is biased */
+ distance--;
+
+ if (!distance) {
+ /* zero distance means a run */
+ uint8_t x = ip[-1];
+ while (ip < ip_bound)
+ if (*ref++ != x)
+ break;
+ else
+ ip++;
+ } else
+ for (;;) {
+ /* safe because the outer check against ip limit */
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ while (ip < ip_bound)
+ if (*ref++ != *ip++) break;
+ break;
+ }
+
+ /* if we have copied something, adjust the copy count */
+ if (copy) /* copy is biased, '0' means 1 byte copy */
+ *(op - copy - 1) = copy - 1;
+ else
+ /* back, to overwrite the copy count */
+ op--;
+
+ /* reset literal counter */
+ copy = 0;
+
+ /* length is biased, '1' means a match of 3 bytes */
+ ip -= 3;
+ len = ip - anchor;
+
+ /* encode the match */
+ if (FASTLZ_UNLIKELY(len > MAX_LEN - 2))
+ while (len > MAX_LEN - 2) {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = MAX_LEN - 2 - 7 - 2;
+ *op++ = (distance & 255);
+ len -= MAX_LEN - 2;
+ }
+
+ if (len < 7) {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ } else {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = len - 7;
+ *op++ = (distance & 255);
+ }
+
+ /* update the hash at match boundary */
+ HASH_FUNCTION(hval, ip);
+ htab[hval] = ip++;
+ HASH_FUNCTION(hval, ip);
+ htab[hval] = ip++;
+
+ /* assuming literal copy */
+ *op++ = MAX_COPY - 1;
+
+ continue;
+
+ literal:
+ *op++ = *anchor++;
+ ip = anchor;
+ copy++;
+ if (FASTLZ_UNLIKELY(copy == MAX_COPY)) {
+ copy = 0;
+ *op++ = MAX_COPY - 1;
+ }
+ }
+
+ /* left-over as literal copy */
+ ip_bound++;
+ while (ip <= ip_bound) {
+ *op++ = *ip++;
+ copy++;
+ if (copy == MAX_COPY) {
+ copy = 0;
+ *op++ = MAX_COPY - 1;
+ }
+ }
+
+ /* if we have copied something, adjust the copy length */
+ if (copy)
+ *(op - copy - 1) = copy - 1;
+ else
+ op--;
+
+ return op - (uint8_t*)output;
}
-int fastlz_decompress(const void* input, int length, void* output, int maxout)
-{
- /* magic identifier for compression level */
- int level = ((*(const flzuint8*)input) >> 5) + 1;
+#if defined(FASTLZ_USE_MEMMOVE) && (FASTLZ_USE_MEMMOVE == 0)
- if(level == 1)
- return fastlz1_decompress(input, length, output, maxout);
- if(level == 2)
- return fastlz2_decompress(input, length, output, maxout);
+static void fastlz_memmove(uint8_t* dest, const uint8_t* src, uint32_t count) {
+ do {
+ *dest++ = *src++;
+ } while (--count);
+}
- /* unknown level, trigger error */
- return 0;
+static void fastlz_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count) {
+ return fastlz_memmove(dest, src, count);
}
-int fastlz_compress_level(int level, const void* input, int length, void* output)
-{
- if(level == 1)
- return fastlz1_compress(input, length, output);
- if(level == 2)
- return fastlz2_compress(input, length, output);
+#else
- return 0;
+#include <string.h>
+
+static void fastlz_memmove(uint8_t* dest, const uint8_t* src, uint32_t count) {
+ if ((count > 4) && (dest >= src + count)) {
+ memmove(dest, src, count);
+ } else {
+ switch (count) {
+ default:
+ do {
+ *dest++ = *src++;
+ } while (--count);
+ break;
+ case 3:
+ *dest++ = *src++;
+ case 2:
+ *dest++ = *src++;
+ case 1:
+ *dest++ = *src++;
+ case 0:
+ break;
+ }
+ }
+}
+
+static void fastlz_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count) {
+ memcpy(dest, src, count);
}
-#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
+#endif
-static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
-{
- const flzuint8* ip = (const flzuint8*) input;
- const flzuint8* ip_bound = ip + length - 2;
- const flzuint8* ip_limit = ip + length - 12;
- flzuint8* op = (flzuint8*) output;
+int fastlz1_decompress(const void* input, int length, void* output,
+ int maxout) {
+ const uint8_t* ip = (const uint8_t*)input;
+ const uint8_t* ip_limit = ip + length;
+ const uint8_t* ip_bound = ip_limit - 2;
+ uint8_t* op = (uint8_t*)output;
+ uint8_t* op_limit = op + maxout;
+ uint32_t ctrl = (*ip++) & 31;
+
+ while (1) {
+ if (ctrl >= 32) {
+ uint32_t len = (ctrl >> 5) - 1;
+ uint32_t ofs = (ctrl & 31) << 8;
+ const uint8_t* ref = op - ofs - 1;
+ if (len == 7 - 1) {
+ FASTLZ_BOUND_CHECK(ip <= ip_bound);
+ len += *ip++;
+ }
+ ref -= *ip++;
+ len += 3;
+ FASTLZ_BOUND_CHECK(op + len <= op_limit);
+ FASTLZ_BOUND_CHECK(ref >= (uint8_t*)output);
+ fastlz_memmove(op, ref, len);
+ op += len;
+ } else {
+ ctrl++;
+ FASTLZ_BOUND_CHECK(op + ctrl <= op_limit);
+ FASTLZ_BOUND_CHECK(ip + ctrl <= ip_limit);
+ fastlz_memcpy(op, ip, ctrl);
+ ip += ctrl;
+ op += ctrl;
+ }
- const flzuint8* htab[HASH_SIZE];
- const flzuint8** hslot;
- flzuint32 hval;
+ if (FASTLZ_UNLIKELY(ip > ip_bound)) break;
+ ctrl = *ip++;
+ }
+
+ return op - (uint8_t*)output;
+}
- flzuint32 copy;
+int fastlz2_compress(const void* input, int length, void* output) {
+ const uint8_t* ip = (const uint8_t*)input;
+ const uint8_t* ip_bound = ip + length - 2;
+ const uint8_t* ip_limit = ip + length - 12 - 1;
+ uint8_t* op = (uint8_t*)output;
+
+ const uint8_t* htab[HASH_SIZE];
+ uint32_t hval;
+
+ uint32_t copy;
/* sanity check */
- if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
- {
- if(length)
- {
+ if (FASTLZ_UNLIKELY(length < 4)) {
+ if (length) {
/* create literal copy only */
- *op++ = length-1;
+ *op++ = length - 1;
ip_bound++;
- while(ip <= ip_bound)
- *op++ = *ip++;
- return length+1;
- }
- else
+ while (ip <= ip_bound) *op++ = *ip++;
+ return length + 1;
+ } else
return 0;
}
/* initializes hash table */
- for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
- *hslot = ip;
+ for (hval = 0; hval < HASH_SIZE; ++hval) htab[hval] = ip;
/* we start with literal copy */
copy = 2;
- *op++ = MAX_COPY-1;
+ *op++ = MAX_COPY - 1;
*op++ = *ip++;
*op++ = *ip++;
/* main loop */
- while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
- {
- const flzuint8* ref;
- flzuint32 distance;
+ while (FASTLZ_LIKELY(ip < ip_limit)) {
+ const uint8_t* ref;
+ uint32_t distance;
/* minimum match length */
- flzuint32 len = 3;
+ uint32_t len = 3;
/* comparison starting-point */
- const flzuint8* anchor = ip;
+ const uint8_t* anchor = ip;
/* check for a run */
-#if FASTLZ_LEVEL==2
- if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
- {
+ if (ip[0] == ip[-1] && ip[0] == ip[1] && ip[1] == ip[2]) {
distance = 1;
ip += 3;
ref = anchor - 1 + 3;
goto match;
}
-#endif
/* find potential match */
- HASH_FUNCTION(hval,ip);
- hslot = htab + hval;
+ HASH_FUNCTION(hval, ip);
ref = htab[hval];
+ /* update hash table */
+ htab[hval] = anchor;
+
/* calculate distance to the match */
distance = anchor - ref;
- /* update hash table */
- *hslot = anchor;
-
/* is this a match? check the first 3 bytes */
- if(distance==0 ||
-#if FASTLZ_LEVEL==1
- (distance >= MAX_DISTANCE) ||
-#else
- (distance >= MAX_FARDISTANCE) ||
-#endif
- *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
+ if (distance == 0 || (distance >= MAX_FARDISTANCE) || *ref++ != *ip++ ||
+ *ref++ != *ip++ || *ref++ != *ip++)
goto literal;
-#if FASTLZ_LEVEL==2
/* far, needs at least 5-byte match */
- if(distance >= MAX_DISTANCE)
- {
- if(*ip++ != *ref++ || *ip++!= *ref++)
- goto literal;
+ if (distance >= MAX_L2_DISTANCE) {
+ if (*ip++ != *ref++ || *ip++ != *ref++) goto literal;
len += 2;
}
-
- match:
-#endif
+
+ match:
/* last matched byte */
ip = anchor + len;
@@ -264,34 +397,33 @@ static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void*
/* distance is biased */
distance--;
- if(!distance)
- {
+ if (!distance) {
/* zero distance means a run */
- flzuint8 x = ip[-1];
- while(ip < ip_bound)
- if(*ref++ != x) break; else ip++;
- }
- else
- for(;;)
- {
- /* safe because the outer check against ip limit */
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- while(ip < ip_bound)
- if(*ref++ != *ip++) break;
- break;
- }
+ uint8_t x = ip[-1];
+ while (ip < ip_bound)
+ if (*ref++ != x)
+ break;
+ else
+ ip++;
+ } else
+ for (;;) {
+ /* safe because the outer check against ip limit */
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ while (ip < ip_bound)
+ if (*ref++ != *ip++) break;
+ break;
+ }
/* if we have copied something, adjust the copy count */
- if(copy)
- /* copy is biased, '0' means 1 byte copy */
- *(op-copy-1) = copy-1;
+ if (copy) /* copy is biased, '0' means 1 byte copy */
+ *(op - copy - 1) = copy - 1;
else
/* back, to overwrite the copy count */
op--;
@@ -304,248 +436,156 @@ static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void*
len = ip - anchor;
/* encode the match */
-#if FASTLZ_LEVEL==2
- if(distance < MAX_DISTANCE)
- {
- if(len < 7)
- {
+ if (distance < MAX_L2_DISTANCE) {
+ if (len < 7) {
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
- }
- else
- {
+ } else {
*op++ = (7 << 5) + (distance >> 8);
- for(len-=7; len >= 255; len-= 255)
- *op++ = 255;
+ for (len -= 7; len >= 255; len -= 255) *op++ = 255;
*op++ = len;
*op++ = (distance & 255);
}
- }
- else
- {
+ } else {
/* far away, but not yet in the another galaxy... */
- if(len < 7)
- {
- distance -= MAX_DISTANCE;
+ if (len < 7) {
+ distance -= MAX_L2_DISTANCE;
*op++ = (len << 5) + 31;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
- }
- else
- {
- distance -= MAX_DISTANCE;
+ } else {
+ distance -= MAX_L2_DISTANCE;
*op++ = (7 << 5) + 31;
- for(len-=7; len >= 255; len-= 255)
- *op++ = 255;
+ for (len -= 7; len >= 255; len -= 255) *op++ = 255;
*op++ = len;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
}
-#else
-
- if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
- while(len > MAX_LEN-2)
- {
- *op++ = (7 << 5) + (distance >> 8);
- *op++ = MAX_LEN - 2 - 7 -2;
- *op++ = (distance & 255);
- len -= MAX_LEN-2;
- }
-
- if(len < 7)
- {
- *op++ = (len << 5) + (distance >> 8);
- *op++ = (distance & 255);
- }
- else
- {
- *op++ = (7 << 5) + (distance >> 8);
- *op++ = len - 7;
- *op++ = (distance & 255);
- }
-#endif
/* update the hash at match boundary */
- HASH_FUNCTION(hval,ip);
+ HASH_FUNCTION(hval, ip);
htab[hval] = ip++;
- HASH_FUNCTION(hval,ip);
+ HASH_FUNCTION(hval, ip);
htab[hval] = ip++;
/* assuming literal copy */
- *op++ = MAX_COPY-1;
+ *op++ = MAX_COPY - 1;
continue;
- literal:
- *op++ = *anchor++;
- ip = anchor;
- copy++;
- if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
- {
- copy = 0;
- *op++ = MAX_COPY-1;
- }
+ literal:
+ *op++ = *anchor++;
+ ip = anchor;
+ copy++;
+ if (FASTLZ_UNLIKELY(copy == MAX_COPY)) {
+ copy = 0;
+ *op++ = MAX_COPY - 1;
+ }
}
/* left-over as literal copy */
ip_bound++;
- while(ip <= ip_bound)
- {
+ while (ip <= ip_bound) {
*op++ = *ip++;
copy++;
- if(copy == MAX_COPY)
- {
+ if (copy == MAX_COPY) {
copy = 0;
- *op++ = MAX_COPY-1;
+ *op++ = MAX_COPY - 1;
}
}
/* if we have copied something, adjust the copy length */
- if(copy)
- *(op-copy-1) = copy-1;
+ if (copy)
+ *(op - copy - 1) = copy - 1;
else
op--;
-#if FASTLZ_LEVEL==2
/* marker for fastlz2 */
- *(flzuint8*)output |= (1 << 5);
-#endif
+ *(uint8_t*)output |= (1 << 5);
- return op - (flzuint8*)output;
+ return op - (uint8_t*)output;
}
-static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
-{
- const flzuint8* ip = (const flzuint8*) input;
- const flzuint8* ip_limit = ip + length;
- flzuint8* op = (flzuint8*) output;
- flzuint8* op_limit = op + maxout;
- flzuint32 ctrl = (*ip++) & 31;
- int loop = 1;
-
- do
- {
- const flzuint8* ref = op;
- flzuint32 len = ctrl >> 5;
- flzuint32 ofs = (ctrl & 31) << 8;
-
- if(ctrl >= 32)
- {
-#if FASTLZ_LEVEL==2
- flzuint8 code;
-#endif
- len--;
- ref -= ofs;
- if (len == 7-1)
-#if FASTLZ_LEVEL==1
- len += *ip++;
- ref -= *ip++;
-#else
- do
- {
+int fastlz2_decompress(const void* input, int length, void* output,
+ int maxout) {
+ const uint8_t* ip = (const uint8_t*)input;
+ const uint8_t* ip_limit = ip + length;
+ const uint8_t* ip_bound = ip_limit - 2;
+ uint8_t* op = (uint8_t*)output;
+ uint8_t* op_limit = op + maxout;
+ uint32_t ctrl = (*ip++) & 31;
+
+ while (1) {
+ if (ctrl >= 32) {
+ uint32_t len = (ctrl >> 5) - 1;
+ uint32_t ofs = (ctrl & 31) << 8;
+ const uint8_t* ref = op - ofs - 1;
+
+ uint8_t code;
+ if (len == 7 - 1) do {
+ FASTLZ_BOUND_CHECK(ip <= ip_bound);
code = *ip++;
len += code;
- } while (code==255);
+ } while (code == 255);
code = *ip++;
ref -= code;
+ len += 3;
/* match from 16-bit distance */
- if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
- if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
- {
- ofs = (*ip++) << 8;
- ofs += *ip++;
- ref = op - ofs - MAX_DISTANCE;
- }
-#endif
-
-#ifdef FASTLZ_SAFE
- if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
- return 0;
-
- if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
- return 0;
-#endif
-
- if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
- ctrl = *ip++;
- else
- loop = 0;
-
- if(ref == op)
- {
- /* optimize copy for a run */
- flzuint8 b = ref[-1];
- *op++ = b;
- *op++ = b;
- *op++ = b;
- for(; len; --len)
- *op++ = b;
- }
- else
- {
-#if !defined(FASTLZ_STRICT_ALIGN)
- const flzuint16* p;
- flzuint16* q;
-#endif
- /* copy from reference */
- ref--;
- *op++ = *ref++;
- *op++ = *ref++;
- *op++ = *ref++;
-
-#if !defined(FASTLZ_STRICT_ALIGN)
- /* copy a byte, so that now it's word aligned */
- if(len & 1)
- {
- *op++ = *ref++;
- len--;
+ if (FASTLZ_UNLIKELY(code == 255))
+ if (FASTLZ_LIKELY(ofs == (31 << 8))) {
+ FASTLZ_BOUND_CHECK(ip < ip_bound);
+ ofs = (*ip++) << 8;
+ ofs += *ip++;
+ ref = op - ofs - MAX_L2_DISTANCE - 1;
}
- /* copy 16-bit at once */
- q = (flzuint16*) op;
- op += len;
- p = (const flzuint16*) ref;
- for(len>>=1; len > 4; len-=4)
- {
- *q++ = *p++;
- *q++ = *p++;
- *q++ = *p++;
- *q++ = *p++;
- }
- for(; len; --len)
- *q++ = *p++;
-#else
- for(; len; --len)
- *op++ = *ref++;
-#endif
- }
- }
- else
- {
+ FASTLZ_BOUND_CHECK(op + len <= op_limit);
+ FASTLZ_BOUND_CHECK(ref >= (uint8_t*)output);
+ fastlz_memmove(op, ref, len);
+ op += len;
+ } else {
ctrl++;
-#ifdef FASTLZ_SAFE
- if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
- return 0;
- if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
- return 0;
-#endif
-
- *op++ = *ip++;
- for(--ctrl; ctrl; ctrl--)
- *op++ = *ip++;
-
- loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
- if(loop)
- ctrl = *ip++;
+ FASTLZ_BOUND_CHECK(op + ctrl <= op_limit);
+ FASTLZ_BOUND_CHECK(ip + ctrl <= ip_limit);
+ fastlz_memcpy(op, ip, ctrl);
+ ip += ctrl;
+ op += ctrl;
}
+
+ if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
+ ctrl = *ip++;
}
- while(FASTLZ_EXPECT_CONDITIONAL(loop));
- return op - (flzuint8*)output;
+ return op - (uint8_t*)output;
}
-#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
+int fastlz_compress(const void* input, int length, void* output) {
+ /* for short block, choose fastlz1 */
+ if (length < 65536) return fastlz1_compress(input, length, output);
+
+ /* else... */
+ return fastlz2_compress(input, length, output);
+}
+
+int fastlz_decompress(const void* input, int length, void* output, int maxout) {
+ /* magic identifier for compression level */
+ int level = ((*(const uint8_t*)input) >> 5) + 1;
+
+ if (level == 1) return fastlz1_decompress(input, length, output, maxout);
+ if (level == 2) return fastlz2_decompress(input, length, output, maxout);
+
+ /* unknown level, trigger error */
+ return 0;
+}
+
+int fastlz_compress_level(int level, const void* input, int length,
+ void* output) {
+ if (level == 1) return fastlz1_compress(input, length, output);
+ if (level == 2) return fastlz2_compress(input, length, output);
+
+ return 0;
+}
diff --git a/thirdparty/misc/fastlz.h b/thirdparty/misc/fastlz.h
index e5ca8dfc02..e53dbfbb56 100644
--- a/thirdparty/misc/fastlz.h
+++ b/thirdparty/misc/fastlz.h
@@ -1,9 +1,6 @@
/*
- FastLZ - lightning-fast lossless compression library
-
- Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
- Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
- Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+ FastLZ - Byte-aligned LZ77 compression library
+ Copyright (C) 2005-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -27,15 +24,15 @@
#ifndef FASTLZ_H
#define FASTLZ_H
-#define FASTLZ_VERSION 0x000100
+#define FASTLZ_VERSION 0x000500
-#define FASTLZ_VERSION_MAJOR 0
-#define FASTLZ_VERSION_MINOR 0
-#define FASTLZ_VERSION_REVISION 0
+#define FASTLZ_VERSION_MAJOR 0
+#define FASTLZ_VERSION_MINOR 5
+#define FASTLZ_VERSION_REVISION 0
-#define FASTLZ_VERSION_STRING "0.1.0"
+#define FASTLZ_VERSION_STRING "0.5.0"
-#if defined (__cplusplus)
+#if defined(__cplusplus)
extern "C" {
#endif
@@ -51,9 +48,18 @@ extern "C" {
length (input buffer size).
The input buffer and the output buffer can not overlap.
+
+ Compression level can be specified in parameter level. At the moment,
+ only level 1 and level 2 are supported.
+ Level 1 is the fastest compression and generally useful for short data.
+ Level 2 is slightly slower but it gives better compression ratio.
+
+ Note that the compressed data, regardless of the level, can always be
+ decompressed using the function fastlz_decompress below.
*/
-int fastlz_compress(const void* input, int length, void* output);
+int fastlz_compress_level(int level, const void* input, int length,
+ void* output);
/**
Decompress a block of compressed data and returns the size of the
@@ -65,35 +71,27 @@ int fastlz_compress(const void* input, int length, void* output);
Decompression is memory safe and guaranteed not to write the output buffer
more than what is specified in maxout.
+
+ Note that the decompression will always work, regardless of the
+ compression level specified in fastlz_compress_level above (when
+ producing the compressed block).
*/
int fastlz_decompress(const void* input, int length, void* output, int maxout);
/**
- Compress a block of data in the input buffer and returns the size of
- compressed block. The size of input buffer is specified by length. The
- minimum input buffer size is 16.
+ DEPRECATED.
- The output buffer must be at least 5% larger than the input buffer
- and can not be smaller than 66 bytes.
-
- If the input is not compressible, the return value might be larger than
- length (input buffer size).
+ This is similar to fastlz_compress_level above, but with the level
+ automatically chosen.
- The input buffer and the output buffer can not overlap.
-
- Compression level can be specified in parameter level. At the moment,
- only level 1 and level 2 are supported.
- Level 1 is the fastest compression and generally useful for short data.
- Level 2 is slightly slower but it gives better compression ratio.
-
- Note that the compressed data, regardless of the level, can always be
- decompressed using the function fastlz_decompress above.
+ This function is deprecated and it will be completely removed in some future
+ version.
*/
-int fastlz_compress_level(int level, const void* input, int length, void* output);
+int fastlz_compress(const void* input, int length, void* output);
-#if defined (__cplusplus)
+#if defined(__cplusplus)
}
#endif
diff --git a/thirdparty/misc/stb_vorbis.c b/thirdparty/misc/stb_vorbis.c
index 4ab8880d5d..b0d79b1724 100644
--- a/thirdparty/misc/stb_vorbis.c
+++ b/thirdparty/misc/stb_vorbis.c
@@ -1,4 +1,4 @@
-// Ogg Vorbis audio decoder - v1.17 - public domain
+// Ogg Vorbis audio decoder - v1.19 - public domain
// http://nothings.org/stb_vorbis/
//
// Original version written by Sean Barrett in 2007.
@@ -26,13 +26,16 @@
// Terje Mathisen Niklas Frykholm Andy Hill
// Casey Muratori John Bolton Gargaj
// Laurent Gomila Marc LeBlanc Ronny Chevalier
-// Bernhard Wodo Evan Balster alxprd@github
+// Bernhard Wodo Evan Balster github:alxprd
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart
-// manxorist@github saga musix github:infatum
-// Timur Gagiev Maxwell Koo
+// github:manxorist saga musix github:infatum
+// Timur Gagiev Maxwell Koo Peter Waller
+// github:audinowho Dougall Johnson
//
// Partial history:
+// 1.19 - 2020-02-05 - warnings
+// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc.
// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure)
// 1.16 - 2019-03-04 - fix warnings
// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found
@@ -130,9 +133,20 @@ typedef struct
int max_frame_size;
} stb_vorbis_info;
+typedef struct
+{
+ char *vendor;
+
+ int comment_list_length;
+ char **comment_list;
+} stb_vorbis_comment;
+
// get general information about the file
extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f);
+// get ogg comments
+extern stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f);
+
// get the last error detected (clears it, too)
extern int stb_vorbis_get_error(stb_vorbis *f);
@@ -759,6 +773,10 @@ struct stb_vorbis
unsigned int temp_memory_required;
unsigned int setup_temp_memory_required;
+ char *vendor;
+ int comment_list_length;
+ char **comment_list;
+
// input config
#ifndef STB_VORBIS_NO_STDIO
FILE *f;
@@ -774,8 +792,11 @@ struct stb_vorbis
uint8 push_mode;
+ // the page to seek to when seeking to start, may be zero
uint32 first_audio_page_offset;
+ // p_first is the page on which the first audio packet ends
+ // (but not necessarily the page on which it starts)
ProbedPage p_first, p_last;
// memory management
@@ -888,7 +909,7 @@ static int error(vorb *f, enum STBVorbisError e)
#define array_size_required(count,size) (count*(sizeof(void *)+(size)))
#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size))
-#define temp_free(f,p) 0
+#define temp_free(f,p) (void)0
#define temp_alloc_save(f) ((f)->temp_offset)
#define temp_alloc_restore(f,p) ((f)->temp_offset = (p))
@@ -909,7 +930,7 @@ static void *make_block_array(void *mem, int count, int size)
static void *setup_malloc(vorb *f, int sz)
{
- sz = (sz+3) & ~3;
+ sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs.
f->setup_memory_required += sz;
if (f->alloc.alloc_buffer) {
void *p = (char *) f->alloc.alloc_buffer + f->setup_offset;
@@ -928,7 +949,7 @@ static void setup_free(vorb *f, void *p)
static void *setup_temp_malloc(vorb *f, int sz)
{
- sz = (sz+3) & ~3;
+ sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs.
if (f->alloc.alloc_buffer) {
if (f->temp_offset - sz < f->setup_offset) return NULL;
f->temp_offset -= sz;
@@ -940,7 +961,7 @@ static void *setup_temp_malloc(vorb *f, int sz)
static void setup_temp_free(vorb *f, void *p, int sz)
{
if (f->alloc.alloc_buffer) {
- f->temp_offset += (sz+3)&~3;
+ f->temp_offset += (sz+7)&~7;
return;
}
free(p);
@@ -1404,6 +1425,9 @@ static int capture_pattern(vorb *f)
static int start_page_no_capturepattern(vorb *f)
{
uint32 loc0,loc1,n;
+ if (f->first_decode && !IS_PUSH_MODE(f)) {
+ f->p_first.page_start = stb_vorbis_get_file_offset(f) - 4;
+ }
// stream structure version
if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version);
// header flag
@@ -1440,15 +1464,12 @@ static int start_page_no_capturepattern(vorb *f)
}
if (f->first_decode) {
int i,len;
- ProbedPage p;
len = 0;
for (i=0; i < f->segment_count; ++i)
len += f->segments[i];
len += 27 + f->segment_count;
- p.page_start = f->first_audio_page_offset;
- p.page_end = p.page_start + len;
- p.last_decoded_sample = loc0;
- f->p_first = p;
+ f->p_first.page_end = f->p_first.page_start + len;
+ f->p_first.last_decoded_sample = loc0;
}
f->next_seg = 0;
return TRUE;
@@ -1539,6 +1560,16 @@ static int get8_packet(vorb *f)
return x;
}
+static int get32_packet(vorb *f)
+{
+ uint32 x;
+ x = get8_packet(f);
+ x += get8_packet(f) << 8;
+ x += get8_packet(f) << 16;
+ x += (uint32) get8_packet(f) << 24;
+ return x;
+}
+
static void flush_packet(vorb *f)
{
while (get8_packet_raw(f) != EOP);
@@ -2130,47 +2161,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
++class_set;
#endif
}
- } else if (ch == 1) {
- while (pcount < part_read) {
- int z = r->begin + pcount*r->part_size;
- int c_inter = 0, p_inter = z;
- if (pass == 0) {
- Codebook *c = f->codebooks+r->classbook;
- int q;
- DECODE(q,f,c);
- if (q == EOP) goto done;
- #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
- part_classdata[0][class_set] = r->classdata[q];
- #else
- for (i=classwords-1; i >= 0; --i) {
- classifications[0][i+pcount] = q % r->classifications;
- q /= r->classifications;
- }
- #endif
- }
- for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
- int z = r->begin + pcount*r->part_size;
- #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
- int c = part_classdata[0][class_set][i];
- #else
- int c = classifications[0][pcount];
- #endif
- int b = r->residue_books[c][pass];
- if (b >= 0) {
- Codebook *book = f->codebooks + b;
- if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
- goto done;
- } else {
- z += r->part_size;
- c_inter = 0;
- p_inter = z;
- }
- }
- #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
- ++class_set;
- #endif
- }
- } else {
+ } else if (ch > 2) {
while (pcount < part_read) {
int z = r->begin + pcount*r->part_size;
int c_inter = z % ch, p_inter = z/ch;
@@ -3504,7 +3495,7 @@ static int vorbis_pump_first_frame(stb_vorbis *f)
}
#ifndef STB_VORBIS_NO_PUSHDATA_API
-static int is_whole_packet_present(stb_vorbis *f, int end_page)
+static int is_whole_packet_present(stb_vorbis *f)
{
// make sure that we have the packet available before continuing...
// this requires a full ogg parse, but we know we can fetch from f->stream
@@ -3524,8 +3515,6 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page)
break;
}
// either this continues, or it ends it...
- if (end_page)
- if (s < f->segment_count-1) return error(f, VORBIS_invalid_stream);
if (s == f->segment_count)
s = -1; // set 'crosses page' flag
if (p > f->stream_end) return error(f, VORBIS_need_more_data);
@@ -3558,8 +3547,6 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page)
if (q[s] < 255)
break;
}
- if (end_page)
- if (s < n-1) return error(f, VORBIS_invalid_stream);
if (s == n)
s = -1; // set 'crosses page' flag
if (p > f->stream_end) return error(f, VORBIS_need_more_data);
@@ -3576,6 +3563,7 @@ static int start_decoder(vorb *f)
int longest_floorlist=0;
// first page, first packet
+ f->first_decode = TRUE;
if (!start_page(f)) return FALSE;
// validate page flag
@@ -3633,6 +3621,41 @@ static int start_decoder(vorb *f)
if (!start_page(f)) return FALSE;
if (!start_packet(f)) return FALSE;
+
+ if (!next_segment(f)) return FALSE;
+
+ if (get8_packet(f) != VORBIS_packet_comment) return error(f, VORBIS_invalid_setup);
+ for (i=0; i < 6; ++i) header[i] = get8_packet(f);
+ if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup);
+ //file vendor
+ len = get32_packet(f);
+ f->vendor = (char*)setup_malloc(f, sizeof(char) * (len+1));
+ for(i=0; i < len; ++i) {
+ f->vendor[i] = get8_packet(f);
+ }
+ f->vendor[len] = (char)'\0';
+ //user comments
+ f->comment_list_length = get32_packet(f);
+ f->comment_list = (char**)setup_malloc(f, sizeof(char*) * (f->comment_list_length));
+
+ for(i=0; i < f->comment_list_length; ++i) {
+ len = get32_packet(f);
+ f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1));
+
+ for(j=0; j < len; ++j) {
+ f->comment_list[i][j] = get8_packet(f);
+ }
+ f->comment_list[i][len] = (char)'\0';
+ }
+
+ // framing_flag
+ x = get8_packet(f);
+ if (!(x & 1)) return error(f, VORBIS_invalid_setup);
+
+
+ skip(f, f->bytes_in_seg);
+ f->bytes_in_seg = 0;
+
do {
len = next_segment(f);
skip(f, len);
@@ -3644,7 +3667,7 @@ static int start_decoder(vorb *f)
#ifndef STB_VORBIS_NO_PUSHDATA_API
if (IS_PUSH_MODE(f)) {
- if (!is_whole_packet_present(f, TRUE)) {
+ if (!is_whole_packet_present(f)) {
// convert error in ogg header to write type
if (f->error == VORBIS_invalid_stream)
f->error = VORBIS_invalid_setup;
@@ -3947,7 +3970,7 @@ static int start_decoder(vorb *f)
g->sorted_order[j] = (uint8) p[j].id;
// precompute the neighbors
for (j=2; j < g->values; ++j) {
- int low,hi;
+ int low = 0,hi = 0;
neighbors(g->Xlist, j, &low,&hi);
g->neighbors[j][0] = low;
g->neighbors[j][1] = hi;
@@ -4132,7 +4155,6 @@ static int start_decoder(vorb *f)
f->temp_memory_required = imdct_mem;
}
- f->first_decode = TRUE;
if (f->alloc.alloc_buffer) {
assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes);
@@ -4141,7 +4163,17 @@ static int start_decoder(vorb *f)
return error(f, VORBIS_outofmem);
}
- f->first_audio_page_offset = stb_vorbis_get_file_offset(f);
+ // @TODO: stb_vorbis_seek_start expects first_audio_page_offset to point to a page
+ // without PAGEFLAG_continued_packet, so this either points to the first page, or
+ // the page after the end of the headers. It might be cleaner to point to a page
+ // in the middle of the headers, when that's the page where the first audio packet
+ // starts, but we'd have to also correctly skip the end of any continued packet in
+ // stb_vorbis_seek_start.
+ if (f->next_seg == -1) {
+ f->first_audio_page_offset = stb_vorbis_get_file_offset(f);
+ } else {
+ f->first_audio_page_offset = 0;
+ }
return TRUE;
}
@@ -4149,6 +4181,13 @@ static int start_decoder(vorb *f)
static void vorbis_deinit(stb_vorbis *p)
{
int i,j;
+
+ setup_free(p, p->vendor);
+ for (i=0; i < p->comment_list_length; ++i) {
+ setup_free(p, p->comment_list[i]);
+ }
+ setup_free(p, p->comment_list);
+
if (p->residue_config) {
for (i=0; i < p->residue_count; ++i) {
Residue *r = p->residue_config+i;
@@ -4248,6 +4287,15 @@ stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f)
return d;
}
+stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f)
+{
+ stb_vorbis_comment d;
+ d.vendor = f->vendor;
+ d.comment_list_length = f->comment_list_length;
+ d.comment_list = f->comment_list;
+ return d;
+}
+
int stb_vorbis_get_error(stb_vorbis *f)
{
int e = f->error;
@@ -4389,7 +4437,7 @@ int stb_vorbis_decode_frame_pushdata(
f->error = VORBIS__no_error;
// check that we have the entire packet in memory
- if (!is_whole_packet_present(f, FALSE)) {
+ if (!is_whole_packet_present(f)) {
*samples = 0;
return 0;
}
@@ -4625,8 +4673,8 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
{
ProbedPage left, right, mid;
int i, start_seg_with_known_loc, end_pos, page_start;
- uint32 delta, stream_length, padding;
- double offset, bytes_per_sample;
+ uint32 delta, stream_length, padding, last_sample_limit;
+ double offset = 0.0, bytes_per_sample = 0.0;
int probe = 0;
// find the last page and validate the target sample
@@ -4639,9 +4687,9 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
// indicates should be the granule position (give or take one)).
padding = ((f->blocksize_1 - f->blocksize_0) >> 2);
if (sample_number < padding)
- sample_number = 0;
+ last_sample_limit = 0;
else
- sample_number -= padding;
+ last_sample_limit = sample_number - padding;
left = f->p_first;
while (left.last_decoded_sample == ~0U) {
@@ -4654,9 +4702,12 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
assert(right.last_decoded_sample != ~0U);
// starting from the start is handled differently
- if (sample_number <= left.last_decoded_sample) {
- if (stb_vorbis_seek_start(f))
+ if (last_sample_limit <= left.last_decoded_sample) {
+ if (stb_vorbis_seek_start(f)) {
+ if (f->current_loc > sample_number)
+ return error(f, VORBIS_seek_failed);
return 1;
+ }
return 0;
}
@@ -4673,10 +4724,10 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
// first probe (interpolate)
double data_bytes = right.page_end - left.page_start;
bytes_per_sample = data_bytes / right.last_decoded_sample;
- offset = left.page_start + bytes_per_sample * (sample_number - left.last_decoded_sample);
+ offset = left.page_start + bytes_per_sample * (last_sample_limit - left.last_decoded_sample);
} else {
// second probe (try to bound the other side)
- double error = ((double) sample_number - mid.last_decoded_sample) * bytes_per_sample;
+ double error = ((double) last_sample_limit - mid.last_decoded_sample) * bytes_per_sample;
if (error >= 0 && error < 8000) error = 8000;
if (error < 0 && error > -8000) error = -8000;
offset += error * 2;
@@ -4707,14 +4758,16 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
}
// if we've just found the last page again then we're in a tricky file,
- // and we're close enough.
- if (mid.page_start == right.page_start)
- break;
-
- if (sample_number < mid.last_decoded_sample)
- right = mid;
- else
- left = mid;
+ // and we're close enough (if it wasn't an interpolation probe).
+ if (mid.page_start == right.page_start) {
+ if (probe >= 2 || delta <= 65536)
+ break;
+ } else {
+ if (last_sample_limit < mid.last_decoded_sample)
+ right = mid;
+ else
+ left = mid;
+ }
++probe;
}
@@ -4830,8 +4883,8 @@ int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number)
flush_packet(f);
}
}
- // the next frame will start with the sample
- assert(f->current_loc == sample_number);
+ // the next frame should start with the sample
+ if (f->current_loc != sample_number) return error(f, VORBIS_seek_failed);
return 1;
}
@@ -5173,7 +5226,7 @@ static void convert_samples_short(int buf_c, short **buffer, int b_offset, int d
int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples)
{
- float **output;
+ float **output = NULL;
int len = stb_vorbis_get_frame_float(f, NULL, &output);
if (len > num_samples) len = num_samples;
if (len)