marshal.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. #include <assert.h>
  2. #include <stddef.h>
  3. #include <string.h>
  4. #include "marshal.h"
  5. #include "misc.h"
  6. void BinarySink_put_data(BinarySink *bs, const void *data, size_t len)
  7. {
  8. bs->write(bs, data, len);
  9. }
  10. void BinarySink_put_datapl(BinarySink *bs, ptrlen pl)
  11. {
  12. BinarySink_put_data(bs, pl.ptr, pl.len);
  13. }
  14. void BinarySink_put_padding(BinarySink *bs, size_t len, unsigned char padbyte)
  15. {
  16. char buf[16];
  17. memset(buf, padbyte, sizeof(buf));
  18. while (len > 0) {
  19. size_t thislen = len < sizeof(buf) ? len : sizeof(buf);
  20. bs->write(bs, buf, thislen);
  21. len -= thislen;
  22. }
  23. }
  24. void BinarySink_put_byte(BinarySink *bs, unsigned char val)
  25. {
  26. bs->write(bs, &val, 1);
  27. }
  28. void BinarySink_put_bool(BinarySink *bs, bool val)
  29. {
  30. unsigned char cval = val ? 1 : 0;
  31. bs->write(bs, &cval, 1);
  32. }
  33. void BinarySink_put_uint16(BinarySink *bs, unsigned long val)
  34. {
  35. unsigned char data[2];
  36. PUT_16BIT_MSB_FIRST(data, val);
  37. bs->write(bs, data, sizeof(data));
  38. }
  39. void BinarySink_put_uint32(BinarySink *bs, unsigned long val)
  40. {
  41. unsigned char data[4];
  42. PUT_32BIT_MSB_FIRST(data, val);
  43. bs->write(bs, data, sizeof(data));
  44. }
  45. void BinarySink_put_uint64(BinarySink *bs, uint64_t val)
  46. {
  47. unsigned char data[8];
  48. PUT_64BIT_MSB_FIRST(data, val);
  49. bs->write(bs, data, sizeof(data));
  50. }
  51. void BinarySink_put_string(BinarySink *bs, const void *data, size_t len)
  52. {
  53. /* Check that the string length fits in a uint32, without doing a
  54. * potentially implementation-defined shift of more than 31 bits */
  55. assert((len >> 31) < 2);
  56. BinarySink_put_uint32(bs, len);
  57. bs->write(bs, data, len);
  58. }
  59. void BinarySink_put_stringpl(BinarySink *bs, ptrlen pl)
  60. {
  61. BinarySink_put_string(bs, pl.ptr, pl.len);
  62. }
  63. void BinarySink_put_stringz(BinarySink *bs, const char *str)
  64. {
  65. BinarySink_put_string(bs, str, strlen(str));
  66. }
  67. void BinarySink_put_stringsb(BinarySink *bs, struct strbuf *buf)
  68. {
  69. BinarySink_put_string(bs, buf->s, buf->len);
  70. strbuf_free(buf);
  71. }
  72. void BinarySink_put_asciz(BinarySink *bs, const char *str)
  73. {
  74. bs->write(bs, str, strlen(str) + 1);
  75. }
  76. bool BinarySink_put_pstring(BinarySink *bs, const char *str)
  77. {
  78. size_t len = strlen(str);
  79. if (len > 255)
  80. return false; /* can't write a Pascal-style string this long */
  81. BinarySink_put_byte(bs, len);
  82. bs->write(bs, str, len);
  83. return true;
  84. }
  85. /* ---------------------------------------------------------------------- */
  86. static bool BinarySource_data_avail(BinarySource *src, size_t wanted)
  87. {
  88. if (src->err)
  89. return false;
  90. if (wanted <= src->len - src->pos)
  91. return true;
  92. src->err = BSE_OUT_OF_DATA;
  93. return false;
  94. }
  95. #define avail(wanted) BinarySource_data_avail(src, wanted)
  96. #define advance(dist) (src->pos += dist)
  97. #define here ((const void *)((const unsigned char *)src->data + src->pos))
  98. #define consume(dist) \
  99. ((const void *)((const unsigned char *)src->data + \
  100. ((src->pos += dist) - dist)))
  101. ptrlen BinarySource_get_data(BinarySource *src, size_t wanted)
  102. {
  103. if (!avail(wanted))
  104. return make_ptrlen("", 0);
  105. return make_ptrlen(consume(wanted), wanted);
  106. }
  107. unsigned char BinarySource_get_byte(BinarySource *src)
  108. {
  109. const unsigned char *ucp;
  110. if (!avail(1))
  111. return 0;
  112. ucp = consume(1);
  113. return *ucp;
  114. }
  115. bool BinarySource_get_bool(BinarySource *src)
  116. {
  117. const unsigned char *ucp;
  118. if (!avail(1))
  119. return false;
  120. ucp = consume(1);
  121. return *ucp != 0;
  122. }
  123. unsigned BinarySource_get_uint16(BinarySource *src)
  124. {
  125. const unsigned char *ucp;
  126. if (!avail(2))
  127. return 0;
  128. ucp = consume(2);
  129. return GET_16BIT_MSB_FIRST(ucp);
  130. }
  131. unsigned long BinarySource_get_uint32(BinarySource *src)
  132. {
  133. const unsigned char *ucp;
  134. if (!avail(4))
  135. return 0;
  136. ucp = consume(4);
  137. return GET_32BIT_MSB_FIRST(ucp);
  138. }
  139. uint64_t BinarySource_get_uint64(BinarySource *src)
  140. {
  141. const unsigned char *ucp;
  142. if (!avail(8))
  143. return 0;
  144. ucp = consume(8);
  145. return GET_64BIT_MSB_FIRST(ucp);
  146. }
  147. ptrlen BinarySource_get_string(BinarySource *src)
  148. {
  149. const unsigned char *ucp;
  150. size_t len;
  151. if (!avail(4))
  152. return make_ptrlen("", 0);
  153. ucp = consume(4);
  154. len = GET_32BIT_MSB_FIRST(ucp);
  155. if (!avail(len))
  156. return make_ptrlen("", 0);
  157. return make_ptrlen(consume(len), len);
  158. }
  159. const char *BinarySource_get_asciz(BinarySource *src)
  160. {
  161. const char *start, *end;
  162. if (src->err)
  163. return "";
  164. start = here;
  165. end = memchr(start, '\0', src->len - src->pos);
  166. if (!end) {
  167. src->err = BSE_OUT_OF_DATA;
  168. return "";
  169. }
  170. advance(end + 1 - start);
  171. return start;
  172. }
  173. static ptrlen BinarySource_get_chars_internal(
  174. BinarySource *src, const char *set, bool include)
  175. {
  176. const char *start = here;
  177. while (avail(1)) {
  178. bool present = NULL != strchr(set, *(const char *)consume(0));
  179. if (present != include)
  180. break;
  181. (void) consume(1);
  182. }
  183. const char *end = here;
  184. return make_ptrlen(start, end - start);
  185. }
  186. ptrlen BinarySource_get_chars(BinarySource *src, const char *include_set)
  187. {
  188. return BinarySource_get_chars_internal(src, include_set, true);
  189. }
  190. ptrlen BinarySource_get_nonchars(BinarySource *src, const char *exclude_set)
  191. {
  192. return BinarySource_get_chars_internal(src, exclude_set, false);
  193. }
  194. ptrlen BinarySource_get_chomped_line(BinarySource *src)
  195. {
  196. const char *start, *end;
  197. if (src->err)
  198. return make_ptrlen(here, 0);
  199. start = here;
  200. end = memchr(start, '\n', src->len - src->pos);
  201. if (end)
  202. advance(end + 1 - start);
  203. else
  204. advance(src->len - src->pos);
  205. end = here;
  206. if (end > start && end[-1] == '\n')
  207. end--;
  208. if (end > start && end[-1] == '\r')
  209. end--;
  210. return make_ptrlen(start, end - start);
  211. }
  212. ptrlen BinarySource_get_pstring(BinarySource *src)
  213. {
  214. const unsigned char *ucp;
  215. size_t len;
  216. if (!avail(1))
  217. return make_ptrlen("", 0);
  218. ucp = consume(1);
  219. len = *ucp;
  220. if (!avail(len))
  221. return make_ptrlen("", 0);
  222. return make_ptrlen(consume(len), len);
  223. }
  224. void BinarySource_REWIND_TO__(BinarySource *src, size_t pos)
  225. {
  226. if (pos <= src->len) {
  227. src->pos = pos;
  228. src->err = BSE_NO_ERROR; /* clear any existing error */
  229. } else {
  230. src->pos = src->len;
  231. src->err = BSE_OUT_OF_DATA; /* new error if we rewind out of range */
  232. }
  233. }
  234. static void stdio_sink_write(BinarySink *bs, const void *data, size_t len)
  235. {
  236. stdio_sink *sink = BinarySink_DOWNCAST(bs, stdio_sink);
  237. fwrite(data, 1, len, sink->fp);
  238. }
  239. void stdio_sink_init(stdio_sink *sink, FILE *fp)
  240. {
  241. sink->fp = fp;
  242. BinarySink_INIT(sink, stdio_sink_write);
  243. }
  244. static void bufchain_sink_write(BinarySink *bs, const void *data, size_t len)
  245. {
  246. bufchain_sink *sink = BinarySink_DOWNCAST(bs, bufchain_sink);
  247. bufchain_add(sink->ch, data, len);
  248. }
  249. void bufchain_sink_init(bufchain_sink *sink, bufchain *ch)
  250. {
  251. sink->ch = ch;
  252. BinarySink_INIT(sink, bufchain_sink_write);
  253. }