BencMessageWriter.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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/Object.h"
  16. #include "benc/String.h"
  17. #include "benc/Dict.h"
  18. #include "benc/List.h"
  19. #include "benc/serialization/standard/BencMessageWriter.h"
  20. #include "exception/Er.h"
  21. #include "wire/Message.h"
  22. #include "util/Base10.h"
  23. static Er_DEFUN(void writeGeneric(Object* obj, struct Message* msg));
  24. static Er_DEFUN(void writeListItems(struct List_Item* item, struct Message* msg))
  25. {
  26. if (!item) { Er_ret(); }
  27. Er(writeListItems(item->next, msg));
  28. Er(writeGeneric(item->elem, msg));
  29. Er_ret();
  30. }
  31. static Er_DEFUN(void writeList(List* l, struct Message* msg))
  32. {
  33. Er(Message_epush8(msg, 'e'));
  34. Er(writeListItems(*l, msg));
  35. Er(Message_epush8(msg, 'l'));
  36. Er_ret();
  37. }
  38. static Er_DEFUN(void writeInt(int64_t num, struct Message* msg))
  39. {
  40. Er(Message_epush8(msg, 'e'));
  41. Er(Base10_write(msg, num));
  42. Er(Message_epush8(msg, 'i'));
  43. Er_ret();
  44. }
  45. static Er_DEFUN(void writeString(String* str, struct Message* msg))
  46. {
  47. Er(Message_epush(msg, str->bytes, str->len));
  48. Er(Message_epush8(msg, ':'));
  49. Er(Base10_write(msg, str->len));
  50. Er_ret();
  51. }
  52. static Er_DEFUN(void writeDictEntries(struct Dict_Entry* entry, struct Message* msg))
  53. {
  54. if (!entry) { Er_ret(); }
  55. Er(writeDictEntries(entry->next, msg));
  56. Er(writeGeneric(entry->val, msg));
  57. Er(writeString(entry->key, msg));
  58. Er_ret();
  59. }
  60. static Er_DEFUN(void writeDict(Dict* d, struct Message* msg))
  61. {
  62. Er(Message_epush8(msg, 'e'));
  63. Er(writeDictEntries(*d, msg));
  64. Er(Message_epush8(msg, 'd'));
  65. Er_ret();
  66. }
  67. static Er_DEFUN(void writeGeneric(Object* obj, struct Message* msg))
  68. {
  69. switch (obj->type) {
  70. case Object_STRING: Er(writeString(obj->as.string, msg)); break;
  71. case Object_DICT: Er(writeDict(obj->as.dictionary, msg)); break;
  72. case Object_LIST: Er(writeList(obj->as.list, msg)); break;
  73. case Object_INTEGER: Er(writeInt(obj->as.number, msg)); break;
  74. default: Assert_failure("object of unknown type [%d]", obj->type);
  75. }
  76. Er_ret();
  77. }
  78. Er_DEFUN(void BencMessageWriter_write(Dict* toWrite, struct Message* msg))
  79. {
  80. Er(writeDict(toWrite, msg));
  81. // lucky
  82. if (!((uintptr_t)msg->msgbytes % 8)) { Er_ret(); }
  83. char d = Er(Message_epop8(msg));
  84. Assert_true(d == 'd');
  85. Assert_true(msg->msgbytes[0] != 'e' && "Can't serialize empty messages");
  86. Assert_true(msg->msgbytes[0] >= '1' && msg->msgbytes[0] <= '9');
  87. // put the message into alignment by padding out the number with leading zeros :)
  88. do { Er(Message_epush8(msg, '0')); } while ((uintptr_t)msg->msgbytes % 8);
  89. Er(Message_epop8(msg));
  90. Er(Message_epush8(msg, 'd'));
  91. Er_ret();
  92. }