marshal.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include <assert.h>
  2. #include <stddef.h>
  3. #include <string.h>
  4. #include "marshal.h"
  5. #include "misc.h"
  6. #include "int64.h"
  7. void BinarySink_put_data(BinarySink *bs, const void *data, size_t len)
  8. {
  9. bs->write(bs, data, len);
  10. }
  11. void BinarySink_put_padding(BinarySink *bs, size_t len, unsigned char padbyte)
  12. {
  13. char buf[16];
  14. memset(buf, padbyte, sizeof(buf));
  15. while (len > 0) {
  16. size_t thislen = len < sizeof(buf) ? len : sizeof(buf);
  17. bs->write(bs, buf, thislen);
  18. len -= thislen;
  19. }
  20. }
  21. void BinarySink_put_byte(BinarySink *bs, unsigned char val)
  22. {
  23. bs->write(bs, &val, 1);
  24. }
  25. void BinarySink_put_bool(BinarySink *bs, int val)
  26. {
  27. unsigned char cval = val ? 1 : 0;
  28. bs->write(bs, &cval, 1);
  29. }
  30. void BinarySink_put_uint16(BinarySink *bs, unsigned long val)
  31. {
  32. unsigned char data[2];
  33. PUT_16BIT_MSB_FIRST(data, val);
  34. bs->write(bs, data, sizeof(data));
  35. }
  36. void BinarySink_put_uint32(BinarySink *bs, unsigned long val)
  37. {
  38. unsigned char data[4];
  39. PUT_32BIT_MSB_FIRST(data, val);
  40. bs->write(bs, data, sizeof(data));
  41. }
  42. void BinarySink_put_uint64(BinarySink *bs, uint64 val)
  43. {
  44. BinarySink_put_uint32(bs, val.hi);
  45. BinarySink_put_uint32(bs, val.lo);
  46. }
  47. void BinarySink_put_string(BinarySink *bs, const void *data, size_t len)
  48. {
  49. /* Check that the string length fits in a uint32, without doing a
  50. * potentially implementation-defined shift of more than 31 bits */
  51. assert((len >> 31) < 2);
  52. BinarySink_put_uint32(bs, len);
  53. bs->write(bs, data, len);
  54. }
  55. void BinarySink_put_stringpl(BinarySink *bs, ptrlen pl)
  56. {
  57. BinarySink_put_string(bs, pl.ptr, pl.len);
  58. }
  59. void BinarySink_put_stringz(BinarySink *bs, const char *str)
  60. {
  61. BinarySink_put_string(bs, str, strlen(str));
  62. }
  63. void BinarySink_put_stringsb(BinarySink *bs, struct strbuf *buf)
  64. {
  65. BinarySink_put_string(bs, buf->s, buf->len);
  66. strbuf_free(buf);
  67. }
  68. void BinarySink_put_asciz(BinarySink *bs, const char *str)
  69. {
  70. bs->write(bs, str, strlen(str) + 1);
  71. }
  72. int BinarySink_put_pstring(BinarySink *bs, const char *str)
  73. {
  74. size_t len = strlen(str);
  75. if (len > 255)
  76. return FALSE; /* can't write a Pascal-style string this long */
  77. BinarySink_put_byte(bs, len);
  78. bs->write(bs, str, len);
  79. return TRUE;
  80. }
  81. /* ---------------------------------------------------------------------- */
  82. static int BinarySource_data_avail(BinarySource *src, size_t wanted)
  83. {
  84. if (src->err)
  85. return FALSE;
  86. if (wanted <= src->len - src->pos)
  87. return TRUE;
  88. src->err = BSE_OUT_OF_DATA;
  89. return FALSE;
  90. }
  91. #define avail(wanted) BinarySource_data_avail(src, wanted)
  92. #define advance(dist) (src->pos += dist)
  93. #define here ((const void *)((const unsigned char *)src->data + src->pos))
  94. #define consume(dist) \
  95. ((const void *)((const unsigned char *)src->data + \
  96. ((src->pos += dist) - dist)))
  97. ptrlen BinarySource_get_data(BinarySource *src, size_t wanted)
  98. {
  99. if (!avail(wanted))
  100. return make_ptrlen("", 0);
  101. return make_ptrlen(consume(wanted), wanted);
  102. }
  103. unsigned char BinarySource_get_byte(BinarySource *src)
  104. {
  105. const unsigned char *ucp;
  106. if (!avail(1))
  107. return 0;
  108. ucp = consume(1);
  109. return *ucp;
  110. }
  111. int BinarySource_get_bool(BinarySource *src)
  112. {
  113. const unsigned char *ucp;
  114. if (!avail(1))
  115. return 0;
  116. ucp = consume(1);
  117. return *ucp != 0;
  118. }
  119. unsigned BinarySource_get_uint16(BinarySource *src)
  120. {
  121. const unsigned char *ucp;
  122. if (!avail(2))
  123. return 0;
  124. ucp = consume(2);
  125. return GET_16BIT_MSB_FIRST(ucp);
  126. }
  127. unsigned long BinarySource_get_uint32(BinarySource *src)
  128. {
  129. const unsigned char *ucp;
  130. if (!avail(4))
  131. return 0;
  132. ucp = consume(4);
  133. return GET_32BIT_MSB_FIRST(ucp);
  134. }
  135. uint64 BinarySource_get_uint64(BinarySource *src)
  136. {
  137. const unsigned char *ucp;
  138. uint64 toret;
  139. if (!avail(8)) {
  140. toret.hi = toret.lo = 0;
  141. return toret;
  142. }
  143. ucp = consume(8);
  144. toret.hi = GET_32BIT_MSB_FIRST(ucp);
  145. toret.lo = GET_32BIT_MSB_FIRST(ucp + 4);
  146. return toret;
  147. }
  148. ptrlen BinarySource_get_string(BinarySource *src)
  149. {
  150. const unsigned char *ucp;
  151. size_t len;
  152. if (!avail(4))
  153. return make_ptrlen("", 0);
  154. ucp = consume(4);
  155. len = GET_32BIT_MSB_FIRST(ucp);
  156. if (!avail(len))
  157. return make_ptrlen("", 0);
  158. return make_ptrlen(consume(len), len);
  159. }
  160. const char *BinarySource_get_asciz(BinarySource *src)
  161. {
  162. const char *start, *end;
  163. if (src->err)
  164. return "";
  165. start = here;
  166. end = memchr(start, '\0', src->len - src->pos);
  167. if (!end) {
  168. src->err = BSE_OUT_OF_DATA;
  169. return "";
  170. }
  171. advance(end + 1 - start);
  172. return start;
  173. }
  174. ptrlen BinarySource_get_pstring(BinarySource *src)
  175. {
  176. const unsigned char *ucp;
  177. size_t len;
  178. if (!avail(1))
  179. return make_ptrlen("", 0);
  180. ucp = consume(1);
  181. len = *ucp;
  182. if (!avail(len))
  183. return make_ptrlen("", 0);
  184. return make_ptrlen(consume(len), len);
  185. }