JsonBencMessageReader.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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. #include "benc/serialization/json/JsonBencMessageReader.h"
  16. #include "benc/List.h"
  17. #include "benc/Dict.h"
  18. #include "benc/String.h"
  19. #include "exception/Er.h"
  20. #include "memory/Allocator.h"
  21. #include "wire/Message.h"
  22. #include "util/Gcc.h"
  23. #include "util/Hex.h"
  24. #include "util/Base10.h"
  25. #include <stdbool.h>
  26. struct Context {
  27. struct Message* const msg;
  28. struct Allocator* const alloc;
  29. const bool lax;
  30. int line;
  31. uintptr_t beginningLastLine;
  32. };
  33. static int getColumn(struct Context* ctx)
  34. {
  35. return (uintptr_t) ctx->msg->msgbytes - ctx->beginningLastLine;
  36. }
  37. #define ERROR0(ctx, message) \
  38. return Er__raise(Gcc_SHORT_FILE, Gcc_LINE, ctx->alloc, \
  39. "Error parsing config (line %d column %d): " message, \
  40. ctx->line, getColumn(ctx))
  41. #define ERROR(ctx, message, ...) \
  42. return Er__raise(Gcc_SHORT_FILE, Gcc_LINE, ctx->alloc, \
  43. "Error parsing config (line %d column %d): " message, \
  44. ctx->line, getColumn(ctx), __VA_ARGS__)
  45. static Er_DEFUN(uint8_t peak(struct Context* ctx))
  46. {
  47. if (!Message_getLength(ctx->msg)) { ERROR0(ctx, "Out of content while reading"); }
  48. Er_ret(ctx->msg->msgbytes[0]);
  49. }
  50. static Er_DEFUN(void skip(struct Context* ctx, int num))
  51. {
  52. if (num > Message_getLength(ctx->msg)) { ERROR0(ctx, "Out of content while reading"); }
  53. for (int i = 0; i < num; i++) {
  54. if (ctx->msg->msgbytes[i] == '\n') {
  55. ctx->beginningLastLine = (uintptr_t) &ctx->msg->msgbytes[i];
  56. ctx->line++;
  57. }
  58. }
  59. Er(Message_eshift(ctx->msg, -num));
  60. Er_ret();
  61. }
  62. static Er_DEFUN(bool assertChar(struct Context* ctx, char chr, bool lax))
  63. {
  64. char c = Er(peak(ctx));
  65. if (c != chr) {
  66. if (lax == true) { Er_ret(false); }
  67. ERROR(ctx, "Expected char [%c] but got [%c]", chr, c);
  68. }
  69. Er_ret(true);
  70. }
  71. static Er_DEFUN(void parseComment(struct Context* ctx))
  72. {
  73. Er(assertChar(ctx, '/', false));
  74. Er(skip(ctx, 1));
  75. uint8_t secondChar = Er(peak(ctx));
  76. if (secondChar != '/' && secondChar != '*') { ERROR(ctx, "Unexpected char [%c]", secondChar); }
  77. bool lastCharSplat = false;
  78. for (;;) {
  79. Er(skip(ctx, 1));
  80. uint8_t chr = Er(peak(ctx));
  81. if (lastCharSplat && secondChar == '*' && chr == '/') {
  82. // get rid of the trailing *
  83. Er(skip(ctx, 1));
  84. } else if (secondChar == '/' && chr == '\n') {
  85. } else {
  86. lastCharSplat = (chr == '*');
  87. continue;
  88. }
  89. Er_ret();
  90. }
  91. }
  92. static Er_DEFUN(void parseWhitespaceAndComments(struct Context* ctx))
  93. {
  94. for (;;) {
  95. switch (Er(peak(ctx))) {
  96. case '\n':
  97. case ' ':
  98. case '\r':
  99. case '\t':
  100. Er(skip(ctx, 1));
  101. continue;
  102. case '/':
  103. Er(parseComment(ctx));
  104. continue;
  105. default: break;
  106. }
  107. Er_ret();
  108. }
  109. ERROR0(ctx, "Reached end of message while parsing");
  110. }
  111. static Er_DEFUN(String* parseString(struct Context* ctx))
  112. {
  113. Er(assertChar(ctx, '"', false));
  114. int line = ctx->line;
  115. uintptr_t beginningLastLine = ctx->beginningLastLine;
  116. int msgLen = Message_getLength(ctx->msg);
  117. String* out = NULL;
  118. uint32_t pos = 0;
  119. #define PUSHOUT(chr) do { \
  120. if (out) { \
  121. Assert_true(out->len > pos); \
  122. out->bytes[pos] = (chr); \
  123. } \
  124. pos++; \
  125. } while (0)
  126. // CHECKFILES_IGNORE expecting a ;
  127. for (;;) {
  128. Er(skip(ctx, 1));
  129. uint8_t bchar = Er(peak(ctx));
  130. switch (bchar) {
  131. case '"': {
  132. Er(skip(ctx, 1));
  133. if (out) { Er_ret(out); }
  134. // got the length, reset and then copy the string next cycle
  135. ctx->line = line;
  136. ctx->beginningLastLine = beginningLastLine;
  137. Er(Message_eshift(ctx->msg, msgLen - Message_getLength(ctx->msg)));
  138. out = String_newBinary(NULL, pos, ctx->alloc);
  139. pos = 0;
  140. continue;
  141. }
  142. case '\0':
  143. case '\n': {
  144. ERROR0(ctx, "Unterminated string");
  145. }
  146. case '\\': {
  147. Er(skip(ctx, 1));
  148. uint8_t x = Er(peak(ctx));
  149. Er(skip(ctx, 1));
  150. if (x != 'x') {
  151. ERROR0(ctx, "Char \\ only allowed if followed by x (as in \\xff)");
  152. }
  153. uint8_t high = Er(peak(ctx));
  154. Er(skip(ctx, 1));
  155. uint8_t low = Er(peak(ctx));
  156. int byte = Hex_decodeByte(high, low);
  157. if (byte < 0 || (byte > 255)) { ERROR0(ctx, "Invalid hex encoding"); }
  158. PUSHOUT(byte);
  159. continue;
  160. }
  161. default: {
  162. PUSHOUT(bchar);
  163. continue;
  164. }
  165. }
  166. }
  167. #undef PUSHOUT
  168. }
  169. static Er_DEFUN(int64_t parseInteger(struct Context* ctx))
  170. {
  171. Er_ret( Er(Base10_read(ctx->msg)) );
  172. }
  173. static Er_DEFUN(Object* parseGeneric(struct Context* ctx));
  174. static Er_DEFUN(List* parseList(struct Context* ctx))
  175. {
  176. Er(assertChar(ctx, '[', false));
  177. Er(skip(ctx, 1));
  178. struct List_Item* first = NULL;
  179. struct List_Item* last = NULL;
  180. for (int i = 0; ; i++) {
  181. for (;;) {
  182. Er(parseWhitespaceAndComments(ctx));
  183. // lax mode, allow ,, extra ,,, commas
  184. if (!ctx->lax || Er(peak(ctx)) != ',') { break; }
  185. Er(skip(ctx, 1));
  186. }
  187. if (Er(peak(ctx)) == ']') {
  188. Er(skip(ctx, 1));
  189. List* out = Allocator_malloc(ctx->alloc, sizeof(List));
  190. *out = first;
  191. Er_ret(out);
  192. }
  193. if (i && Er(assertChar(ctx, ',', ctx->lax))) {
  194. Er(skip(ctx, 1));
  195. Er(parseWhitespaceAndComments(ctx));
  196. }
  197. struct List_Item* item = Allocator_calloc(ctx->alloc, sizeof(struct List_Item), 1);
  198. item->elem = Er(parseGeneric(ctx));
  199. if (last) {
  200. last->next = item;
  201. } else {
  202. first = item;
  203. }
  204. last = item;
  205. }
  206. }
  207. static Er_DEFUN(Dict* parseDict(struct Context* ctx))
  208. {
  209. Er(assertChar(ctx, '{', false));
  210. Er(skip(ctx, 1));
  211. struct Dict_Entry* last = NULL;
  212. struct Dict_Entry* first = NULL;
  213. for (int i = 0; ; i++) {
  214. for (;;) {
  215. Er(parseWhitespaceAndComments(ctx));
  216. if (!ctx->lax || Er(peak(ctx)) != ',') { break; }
  217. Er(skip(ctx, 1));
  218. }
  219. if (Er(peak(ctx)) == '}') {
  220. Er(skip(ctx, 1));
  221. Dict* out = Allocator_malloc(ctx->alloc, sizeof(Dict));
  222. *out = first;
  223. Er_ret(out);
  224. }
  225. if (i && Er(assertChar(ctx, ',', ctx->lax))) {
  226. Er(skip(ctx, 1));
  227. Er(parseWhitespaceAndComments(ctx));
  228. }
  229. struct Dict_Entry* entry = Allocator_calloc(ctx->alloc, sizeof(struct Dict_Entry), 1);
  230. entry->key = Er(parseString(ctx));
  231. Er(parseWhitespaceAndComments(ctx));
  232. if (Er(assertChar(ctx, ':', ctx->lax))) {
  233. Er(skip(ctx, 1));
  234. Er(parseWhitespaceAndComments(ctx));
  235. }
  236. entry->val = Er(parseGeneric(ctx));
  237. if (last) {
  238. last->next = entry;
  239. } else {
  240. first = entry;
  241. }
  242. last = entry;
  243. }
  244. }
  245. static Er_DEFUN(Object* parseGeneric(struct Context* ctx))
  246. {
  247. Object* out = Allocator_calloc(ctx->alloc, sizeof(Object), 1);
  248. uint8_t c = Er(peak(ctx));
  249. switch (c) {
  250. case '-':
  251. case '0':
  252. case '1':
  253. case '2':
  254. case '3':
  255. case '4':
  256. case '5':
  257. case '6':
  258. case '7':
  259. case '8':
  260. case '9': {
  261. out->type = Object_INTEGER;
  262. out->as.number = Er(parseInteger(ctx));
  263. break;
  264. }
  265. case '[': {
  266. out->type = Object_LIST;
  267. out->as.list = Er(parseList(ctx));
  268. break;
  269. }
  270. case '{': {
  271. out->type = Object_DICT;
  272. out->as.dictionary = Er(parseDict(ctx));
  273. break;
  274. }
  275. case '"': {
  276. out->type = Object_STRING;
  277. out->as.string = Er(parseString(ctx));
  278. break;
  279. }
  280. default:
  281. ERROR(ctx, "While looking for something to parse: "
  282. "expected one of - 0 1 2 3 4 5 6 7 8 9 [ { \", found [%c]", c);
  283. }
  284. Er_ret(out);
  285. }
  286. Er_DEFUN(Dict* JsonBencMessageReader_read(
  287. struct Message* msg,
  288. struct Allocator* alloc,
  289. bool lax
  290. )) {
  291. struct Context ctx = {
  292. .msg = msg,
  293. .alloc = alloc,
  294. .lax = lax,
  295. .line = 1,
  296. .beginningLastLine = (uintptr_t) msg->msgbytes
  297. };
  298. Er_ret( Er(parseDict(&ctx)) );
  299. }
  300. const char* JsonBencMessageReader_readNoExcept(
  301. struct Message* msg,
  302. struct Allocator* alloc,
  303. Dict** outPtr,
  304. bool lax)
  305. {
  306. struct Er_Ret* er = NULL;
  307. Dict* out = Er_check(&er, JsonBencMessageReader_read(msg, alloc, lax));
  308. if (er) {
  309. return er->message;
  310. }
  311. *outPtr = out;
  312. return NULL;
  313. }