aboutsummaryrefslogtreecommitdiff
path: root/Src/nsmkv/vint.cpp
diff options
context:
space:
mode:
authorJean-Francois Mauguit <jfmauguit@mac.com>2024-09-24 09:03:25 -0400
committerGitHub <noreply@github.com>2024-09-24 09:03:25 -0400
commitbab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/nsmkv/vint.cpp
parent4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff)
parent20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff)
downloadwinamp-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.cpp91
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