vint.cpp 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #include <bfc/platform/types.h>
  2. #ifdef _MSC_VER
  3. #include <intrin.h>
  4. static uint32_t __inline clz(uint32_t value)
  5. {
  6. DWORD leading_zero = 0;
  7. if (_BitScanReverse(&leading_zero, value))
  8. {
  9. return 31 - leading_zero;
  10. }
  11. else
  12. {
  13. return 32;
  14. }
  15. }
  16. #endif
  17. uint8_t vint_get_number_bytes(uint8_t first_byte)
  18. {
  19. return (uint8_t)clz((uint32_t)first_byte) - 24;
  20. }
  21. static uint8_t masks[] =
  22. {
  23. 0x7F, // 0111 1111
  24. 0x3F, // 0011 1111
  25. 0x1F, // 0001 1111
  26. 0x0F, // 0000 1111
  27. 0x07, // 0000 0111
  28. 0x03, // 0000 0011
  29. 0x01, // 0000 0001
  30. 0x00, // 0000 0000
  31. };
  32. /* call if you already know the len (e.g. from vint_get_number_bytes earlier */
  33. uint64_t vint_read_ptr_len(uint8_t len, const uint8_t *ptr)
  34. {
  35. uint64_t ret = masks[len] & ptr[0];
  36. while (len--)
  37. {
  38. ret <<= 8;
  39. ret |= *++ptr;
  40. }
  41. return ret;
  42. }
  43. uint64_t vint_read_ptr(const uint8_t *ptr)
  44. {
  45. uint8_t len = vint_get_number_bytes(ptr[0]);
  46. return vint_read_ptr_len(len, ptr);
  47. }
  48. bool vint_unknown_length(uint8_t len, const uint8_t *ptr)
  49. {
  50. if (masks[len] != (masks[len] & ptr[0]))
  51. return false;
  52. while (len--)
  53. {
  54. if (*++ptr == 0xFF)
  55. return false;
  56. }
  57. return true;
  58. }
  59. static int64_t vsint_substr[] =
  60. {
  61. 0x3F,
  62. 0x1FFF,
  63. 0x0FFFFF,
  64. 0x07FFFFFF,
  65. 0x03FFFFFFFF,
  66. 0x01FFFFFFFFFF,
  67. 0x00FFFFFFFFFFFF,
  68. 0x007FFFFFFFFFFFFF,
  69. };
  70. int64_t vsint_read_ptr_len(uint8_t len, const uint8_t *ptr)
  71. {
  72. uint64_t val = vint_read_ptr_len(len, ptr);
  73. return val - vsint_substr[len];
  74. }
  75. int64_t vsint_read_ptr(const uint8_t *ptr)
  76. {
  77. uint8_t len = vint_get_number_bytes(ptr[0]);
  78. uint64_t val = vint_read_ptr(ptr);
  79. return val - vsint_substr[len];
  80. }