VarInt.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #ifndef VarInt_H
  16. #define VarInt_H
  17. #include "util/Bits.h"
  18. #include "util/Gcc.h"
  19. #include <stdint.h>
  20. // Thank you Satoshi
  21. struct VarInt_Iter {
  22. uint8_t* ptr;
  23. uint8_t* end;
  24. uint8_t* start;
  25. };
  26. static inline void VarInt_clone(struct VarInt_Iter* out, const struct VarInt_Iter* in)
  27. {
  28. out->ptr = in->ptr;
  29. out->start = in->start;
  30. out->end = in->end;
  31. }
  32. static inline void VarInt_mk(struct VarInt_Iter* out, uint8_t* ptr, int length)
  33. {
  34. out->ptr = ptr;
  35. out->end = ptr + length;
  36. out->start = ptr;
  37. }
  38. static inline void VarInt_toStart(struct VarInt_Iter* iter)
  39. {
  40. iter->ptr = iter->start;
  41. }
  42. static inline void VarInt_toEnd(struct VarInt_Iter* iter)
  43. {
  44. iter->ptr = iter->end;
  45. }
  46. static inline int VarInt_hasMore(struct VarInt_Iter* iter)
  47. {
  48. return iter->end > iter->ptr;
  49. }
  50. static inline int VarInt_sizeOf(uint64_t val)
  51. {
  52. return (!!(val >> 32)) * 4 + (!!(val >> 16)) * 2 + (!!((val + 3) >> 8)) + 1;
  53. }
  54. static inline int VarInt_pop(struct VarInt_Iter* iter, uint64_t* _out)
  55. {
  56. uint64_t out = 0;
  57. uint8_t* bytes = iter->ptr;
  58. int len = iter->end - bytes;
  59. if (len < 9) {
  60. if (len < 5) {
  61. if (len < 3) {
  62. if (len < 1) { return -1; }
  63. if (*bytes >= 0xfd) { return -1; }
  64. } else if (*bytes >= 0xfe) { return -1; }
  65. } else if (*bytes >= 0xff) { return -1; }
  66. }
  67. switch (*bytes) {
  68. case 0xff:
  69. out |= *++bytes; out <<= 8;
  70. out |= *++bytes; out <<= 8;
  71. out |= *++bytes; out <<= 8;
  72. out |= *++bytes; out <<= 8;
  73. Gcc_FALLTHRU
  74. case 0xfe:
  75. out |= *++bytes; out <<= 8;
  76. out |= *++bytes; out <<= 8;
  77. Gcc_FALLTHRU
  78. case 0xfd:
  79. out |= *++bytes; out <<= 8;
  80. bytes++;
  81. Gcc_FALLTHRU
  82. default:
  83. out |= *bytes++;
  84. }
  85. iter->ptr = bytes;
  86. if (_out) { *_out = out; }
  87. return 0;
  88. }
  89. static inline int VarInt_push(struct VarInt_Iter* iter, uint64_t val)
  90. {
  91. uint8_t* ptr = iter->ptr;
  92. int padding = ptr - iter->start;
  93. if (padding < 9) {
  94. if (padding < 5) {
  95. if (padding < 3) {
  96. if (padding < 1) { return -1; }
  97. if (val > 0xfc) { return -1; }
  98. } else if (val > 0xffff) { return -1; }
  99. } else if (val > 0xffffffff) { return -1; }
  100. }
  101. int i = VarInt_sizeOf(val);
  102. for (int j = 0; j < i; j++) { *--ptr = val & 0xff; val >>= 8; }
  103. switch (i) {
  104. case 8: *--ptr = 0xff; break;
  105. case 4: *--ptr = 0xfe; break;
  106. case 2: *--ptr = 0xfd; break;
  107. }
  108. iter->ptr = ptr;
  109. return 0;
  110. }
  111. #endif