diff options
author | Jean-Francois Mauguit <jfmauguit@mac.com> | 2024-09-24 09:03:25 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-24 09:03:25 -0400 |
commit | bab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/nsmkv/vint.cpp | |
parent | 4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff) | |
parent | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff) | |
download | winamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz |
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/nsmkv/vint.cpp')
-rw-r--r-- | Src/nsmkv/vint.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/Src/nsmkv/vint.cpp b/Src/nsmkv/vint.cpp new file mode 100644 index 00000000..4124f084 --- /dev/null +++ b/Src/nsmkv/vint.cpp @@ -0,0 +1,91 @@ +#include <bfc/platform/types.h> + +#ifdef _MSC_VER +#include <intrin.h> +static uint32_t __inline clz(uint32_t value) +{ + DWORD leading_zero = 0; + if (_BitScanReverse(&leading_zero, value)) + { + return 31 - leading_zero; + } + else + { + return 32; + } +} +#endif + +uint8_t vint_get_number_bytes(uint8_t first_byte) +{ + return (uint8_t)clz((uint32_t)first_byte) - 24; +} + +static uint8_t masks[] = +{ + 0x7F, // 0111 1111 + 0x3F, // 0011 1111 + 0x1F, // 0001 1111 + 0x0F, // 0000 1111 + 0x07, // 0000 0111 + 0x03, // 0000 0011 + 0x01, // 0000 0001 + 0x00, // 0000 0000 +}; + +/* call if you already know the len (e.g. from vint_get_number_bytes earlier */ +uint64_t vint_read_ptr_len(uint8_t len, const uint8_t *ptr) +{ + uint64_t ret = masks[len] & ptr[0]; + + while (len--) + { + ret <<= 8; + ret |= *++ptr; + } + return ret; +} + +uint64_t vint_read_ptr(const uint8_t *ptr) +{ + uint8_t len = vint_get_number_bytes(ptr[0]); + return vint_read_ptr_len(len, ptr); +} + +bool vint_unknown_length(uint8_t len, const uint8_t *ptr) +{ + if (masks[len] != (masks[len] & ptr[0])) + return false; + + while (len--) + { + if (*++ptr == 0xFF) + return false; + } + return true; +} + +static int64_t vsint_substr[] = +{ + 0x3F, + 0x1FFF, + 0x0FFFFF, + 0x07FFFFFF, + 0x03FFFFFFFF, + 0x01FFFFFFFFFF, + 0x00FFFFFFFFFFFF, + 0x007FFFFFFFFFFFFF, +}; + +int64_t vsint_read_ptr_len(uint8_t len, const uint8_t *ptr) +{ + uint64_t val = vint_read_ptr_len(len, ptr); + return val - vsint_substr[len]; +} + +int64_t vsint_read_ptr(const uint8_t *ptr) +{ + uint8_t len = vint_get_number_bytes(ptr[0]); + uint64_t val = vint_read_ptr(ptr); + return val - vsint_substr[len]; +}
\ No newline at end of file |