123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- /* vim: set expandtab ts=4 sw=4: */
- /*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- #include "benc/Object.h"
- #include "benc/String.h"
- #include "benc/Dict.h"
- #include "benc/List.h"
- #include "benc/serialization/standard/BencMessageWriter.h"
- #include "exception/Er.h"
- #include "wire/Message.h"
- #include "util/Base10.h"
- static Er_DEFUN(void writeGeneric(Object* obj, struct Message* msg));
- static Er_DEFUN(void writeListItems(struct List_Item* item, struct Message* msg))
- {
- if (!item) { Er_ret(); }
- Er(writeListItems(item->next, msg));
- Er(writeGeneric(item->elem, msg));
- Er_ret();
- }
- static Er_DEFUN(void writeList(List* l, struct Message* msg))
- {
- Er(Message_epush8(msg, 'e'));
- Er(writeListItems(*l, msg));
- Er(Message_epush8(msg, 'l'));
- Er_ret();
- }
- static Er_DEFUN(void writeInt(int64_t num, struct Message* msg))
- {
- Er(Message_epush8(msg, 'e'));
- Er(Base10_write(msg, num));
- Er(Message_epush8(msg, 'i'));
- Er_ret();
- }
- static Er_DEFUN(void writeString(String* str, struct Message* msg))
- {
- Er(Message_epush(msg, str->bytes, str->len));
- Er(Message_epush8(msg, ':'));
- Er(Base10_write(msg, str->len));
- Er_ret();
- }
- static Er_DEFUN(void writeDictEntries(struct Dict_Entry* entry, struct Message* msg))
- {
- if (!entry) { Er_ret(); }
- Er(writeDictEntries(entry->next, msg));
- Er(writeGeneric(entry->val, msg));
- Er(writeString(entry->key, msg));
- Er_ret();
- }
- static Er_DEFUN(void writeDict(Dict* d, struct Message* msg))
- {
- Er(Message_epush8(msg, 'e'));
- Er(writeDictEntries(*d, msg));
- Er(Message_epush8(msg, 'd'));
- Er_ret();
- }
- static Er_DEFUN(void writeGeneric(Object* obj, struct Message* msg))
- {
- switch (obj->type) {
- case Object_STRING: Er(writeString(obj->as.string, msg)); break;
- case Object_DICT: Er(writeDict(obj->as.dictionary, msg)); break;
- case Object_LIST: Er(writeList(obj->as.list, msg)); break;
- case Object_INTEGER: Er(writeInt(obj->as.number, msg)); break;
- default: Assert_failure("object of unknown type [%d]", obj->type);
- }
- Er_ret();
- }
- Er_DEFUN(void BencMessageWriter_write(Dict* toWrite, struct Message* msg))
- {
- Er(writeDict(toWrite, msg));
- // lucky
- if (!((uintptr_t)msg->msgbytes % 8)) { Er_ret(); }
- char d = Er(Message_epop8(msg));
- Assert_true(d == 'd');
- Assert_true(msg->msgbytes[0] != 'e' && "Can't serialize empty messages");
- Assert_true(msg->msgbytes[0] >= '1' && msg->msgbytes[0] <= '9');
- // put the message into alignment by padding out the number with leading zeros :)
- do { Er(Message_epush8(msg, '0')); } while ((uintptr_t)msg->msgbytes % 8);
- Er(Message_epop8(msg));
- Er(Message_epush8(msg, 'd'));
- Er_ret();
- }
|