marshal.c 7.9 KB

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