BencMessageWriter.c 3.1 KB

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